Nabend
Der ESP soll als Server (AP) gesteuert werden.
Über verschiedene URLs möchte ich vier Zustände aufrufen:
Motor aus, Motor rechts, Motor links -> klappt problemlos
In der vierten Variante soll der ESP zwei Endpunkte erkennen
(digitalRead)
und die Laufrichtung ändern.
Dafür habe ich eine while-Schleife genutzt.
Leider komme ich aus dieser Schleife nicht mehr heraus:
Hier nur der Code des Loops.
Und die Ausgabe des seriellen Monitors:
1
xxx
2
GET /vier HTTP/1.1
3
ccc
4
xxx
5
GET /favicon.ico HTTP/1.1
6
ccc
7
xxx
8
GET /favicon.ico HTTP/1.1
9
ccc
Meine Idee war, das die while-Schleife nur so lange durchlaufen wird,
wie "req" den entsprechenden Inhalt besitzt.
Sind die Favicon Abfragen des Browsers das Problem?
Oder gibt es eine elegantere Möglichkeit?
Kurt schrieb:> Meine Idee war, das die while-Schleife nur so lange durchlaufen wird,> wie "req" den entsprechenden Inhalt besitzt.
Tut es aber, wie auch anders, wenn du den Inhalt von req in der Schlaufe
nicht veränderst.
Wieso erstellst du durch die Benutzung von millis() nicht ein
Pseudo-Betriebssystem in dem bestimmte Routinen nur in bestimmten
Intervallen ausgeführt werden? Dann könntest du Einerseits den Webserver
handeln und auf der anderen Seite die Routine laufen lassen.
Gruss
Felix
Das verstehe ich jetzt noch nicht.
Zur Erklärung:
Ich möchte den 4. Fall (der Schleife) durch das Aufrufen eines anderen
Falles wieder abbrechen können.
Hallo,
dann vereinbare eine Statusvariable, mekr Dir den Zustand bis der sich
ändert.
loop() mit
1
WiFiClient client = server.available();
2
if (!client) {
3
return;
4
}
ist ohnehin keine gute Idee, auch wenn es so jetzt scheinbar klappt.
1
void loop()
2
{
3
WiFiClient client;
4
char status = 0;
5
6
while(1)
7
{
8
if (server.available())
9
{
10
... hier Deine Abfragen
11
if (req.indexOf("/eins") != -1)
12
{
13
status = 1;
14
}
15
... usw.
16
}
17
if (status = 1)
18
{
19
digitalWrite(LS_out_0, LOW);
20
digitalWrite(LS_out_1, LOW);
21
}
22
23
...
24
}
als Ansatz. Eigentlich noch eine Variable old_status, weil Du die
digitalWrite() Sachen ja nur setzen mußt, wenn status sich gegenüber dem
vorigen Druchlauf verändert hat.
PS: warum nimmst Du nicht den ESP9266Webserver?
Wenn man das mehr als nur so nutzen will, macht er das Leben leichter,
man sollte schließlich Webanfragen auch beantworten, der Nutzer will ja
wissen, ob alles geklappt hat.
Gruß aus Bberlin
Michael
Guten Morgen
Entweder verstehe ich deine Antwort einfach nicht,
oder ich habe es immer noch nicht geschafft mein Problem richtig zu
beschreiben.
Michael U. schrieb:> WiFiClient client = server.available();
Das ist doch nur eine Sicherheitsabfrage und hat mit meiner Schleife
nichts zu tun, oder?
Michael U. schrieb:> der Nutzer will ja> wissen, ob alles geklappt hat.
Das kann der Nutzer sehen :-)
Der ESP steuert einen Motor und ich möchte diesen Motor, welcher eine
Seilbahn bewegt, gerne mit dem Handy steuern.
Vor, zurück und stopp, klappt.
Fall vier:
An jedem Ende des Seils ist ein Stück schwarzes Klebeband umwickelt.
Dieses wird durch eine Reflexlichtschranke erkannt und dient somit als
Endschalter.
Somit soll die Seilbahn immer hin und her fahren.
Aber ich muss diesen Fall ja auch wieder stoppen können.
Der Arduino loop ist eine Endlosschleife. Das server.available() liefert
einen WiFiClient zurück, falls einer Vorhanden ist. WiFiClient client =
client.readStringUntil('\r') liefert dann die erste Zeile der HTTP GET
Anfrage zurück, und speichert diese in req. In der while Schleife wird
client.readStringUntil nie aufgerufen, und req nie gesetzt. Ich Empfehle
die Whileschleife wegzulassen, die Schleife in Funktionen auszulagern,
und Statusvariablen einzuführen.
Hallo,
Kurt schrieb:> Entweder verstehe ich deine Antwort einfach nicht,> oder ich habe es immer noch nicht geschafft mein Problem richtig zu> beschreiben.
Naja, ich sollte wohl erst meinen Kaffee zuende trinken bevor ich
schreibe...
> Michael U. schrieb:>> WiFiClient client = server.available();>> Das ist doch nur eine Sicherheitsabfrage und hat mit meiner Schleife> nichts zu tun, oder?
Stimmt, habe ich falsch interpretiert.
Ich versuche es nochmal...
String req = client.readStringUntil('\r');
Du benutzt Streamread um einen Requst des Webclients zu bekommen.
Das kommt entweder zurück, wenn '\r' erkannt wurde oder wenn der Timeout
zuschlägt.
Eigentlich gehört da noch eine Abfrage davor, ob überhaupt ein client
was will, außerden ein Timeout, falls der Request nicht komplett ist.
Da verläßt Du Dich nur auf .readStringUntil
Auf einen ankommenden neuen Requst kann in Schleife vier nie reagiert
werden, er wird ja nicht bearbeitet. Du müßtest also dort mit
client.available() schauen, ob ein neuer Request angekommen ist, diesen
mit client.readStringUntil('\r'); abholen und auswerten.
Das geht real aber nicht wirklich. client-Abfrage, Reqest holen und
auswerten und die Aktionen Deiner Seilbahn mußt Du trennen.
Es müssen ja beide "parallel" laufen, also client abfragen und
gewünschten Status setzen, wenn was da ist, sonst weitermachen.
Seilbahn nach status-Wert bedienen, wenn nötig und wieder zur
client-Abfrage.
> Fall vier:> An jedem Ende des Seils ist ein Stück schwarzes Klebeband umwickelt.> Dieses wird durch eine Reflexlichtschranke erkannt und dient somit als> Endschalter.> Somit soll die Seilbahn immer hin und her fahren.> Aber ich muss diesen Fall ja auch wieder stoppen können.
Bei 4 müssen die delay() raus, das darf nicht blokierend sein.
Also z.B. per mills() abfragen, ob was gemacht werden muß.
Ich habe im Moment keine Zeit, vielleicht macht es das trotzdem etwas
verständlicher, ich melde mich nacher nochmal.
Gruß aus Berlin
Michael
Moin Daniel
Danke für den ganzen Code.
Ich verstehe es zwar noch nicht, aber ich habe mal versucht ihn zu
kompilieren.
Leider gab es folgende Fehlermeldung:
use of enum 'move_state' without previous declaration
bezieht sich wohl auf diese Zeile:
void setState( enum move_state state ){
Kannst du mir da nen Tipp geben?
Hallo Kurt,
um erstmal schnell Deine 4. Schleife loszuwerden:
1
in setup()
2
3
unsigned long startSekunde = 0;
4
unsigned long warteZeit = 500;
5
6
...
7
8
else if (status == 3)
9
{
10
digitalWrite(LS_out_0, LOW);
11
digitalWrite(LS_out_1, HIGH);
12
13
if (warten == false)
14
{
15
if (digitalRead(LS_in_0) == 0)
16
{
17
digitalWrite(LS_out_1, LOW);
18
}
19
else
20
{
21
digitalWrite(LS_out_0, LOW);
22
}
23
startSekunde = millis();
24
warten = true;
25
}
26
else
27
{
28
if (millis() > (startSekunde + warteZeit) // Wartezeit vergangen?
29
{
30
if (digitalRead(LS_in_0) == 0)
31
{
32
digitalWrite(LS_out_0, HIGH);
33
}
34
else
35
{
36
digitalWrite(LS_out_1, HIGH);
37
warten = false; // nicht warten
38
}
39
}
40
}
Ich weiß jetzt nicht, ob ich Deine digitalWrite() richtig sortiert habe,
ansonsten schau Dir eben
http://playground.arduino.cc/Learning/BlinkWithoutDelayDe
mal an.
delay() sollte man sparsam verwenden und nur dann, wenn man in der Zeit
wirklich nichts anderes zu tun hat. Es wartet schließlich einfach und
damit
kann in der Zeit nichts anderes bearbeitet werden.
Dasselbe passiert natürlich in einer while(1) Schleife. Da ist das
Programm dauerhaft wenn man die nicht gewollt wieder verläßt.
Normalerweise ist loop() eben diese Schleife und deren Inhalt muß
möglichst schnell und ständig durchlaufen werden.
Gruß aus Berlin
Michael
Der Ersatz für die while-Schleife sieht vielversprechend aus, will aber
noch nicht auf Anhieb.
Zum besseren Verständnis und vor allem zur einfacheren Handhabung habe
ich mir daraus ein eigenes Sketch gemacht.
So, es funktioniert wie gewünscht :-)
Danke euch Beiden für die Hilfe, auch wenn ich am Ende nicht direkt
etwas von Euren Beispielen verwendet habe.
Zumindest hat mich amiga darauf gest0ßen, wie man die Schleife durch
Bedingungen ersetzten kann.
Ganz fertig ist der Code noch nicht, die delay() könnte noch raus ;-)
Aber das stört in diesem Fall erst einmal nicht.
Jetzt wird etwas gelötet und der kleine Treiber (bzw. das Servo) durch
einen Großen (bzw. einen richtigen Motor) ersetzt.
Hier mal der Code, falls jemand damit etwas anfangen kann:
1
#include <ESP8266WiFi.h>
2
WiFiServer server(80);
3
int PIN_Motor_rechts = D5;
4
int PIN_Motor_links = D6;
5
int PIN_Ende_rechts = D2;
6
int PIN_Ende_links = D1;
7
int ende_rechts = 0;
8
int ende_links = 0;
9
int fahrt_rechts = 1;
10
int fahrt_links = 0;
11
int fall = 0;
12
String req;
13
unsigned long zeit1 = 0;
14
unsigned long zeit2 = 0;
15
16
void setup()
17
{
18
WiFi.mode(WIFI_AP);
19
WiFi.softAP("Seilbahn", "12345678");
20
server.begin();
21
Serial.begin(115200);
22
pinMode(PIN_Motor_rechts, OUTPUT);
23
pinMode(PIN_Motor_links, OUTPUT);
24
pinMode(PIN_Ende_rechts, INPUT);
25
pinMode(PIN_Ende_links, INPUT);
26
digitalWrite(PIN_Motor_rechts, LOW);
27
digitalWrite(PIN_Motor_links, LOW);
28
}
29
30
void loop()
31
{
32
// // // // // // Loopdauer messen
33
Serial.print("Loopdauer: ");
34
Serial.println(millis() - zeit1);
35
zeit1 = millis();
36
37
// // // // // // URL abfragen
38
WiFiClient client = server.available();
39
if (client.available()) {
40
req = client.readStringUntil('\r');
41
client.flush();
42
}
43
44
// // // // // // Fälle den URLs zuordnen
45
if (req.indexOf("/null") != -1) {
46
fall = 0;
47
}
48
else if (req.indexOf("/eins") != -1) {
49
fall = 1;
50
}
51
else if (req.indexOf("/zwei") != -1) {
52
fall = 2;
53
}
54
else if (req.indexOf("/drei") != -1) {
55
fall = 3;
56
}
57
58
// // // // // // Fälle führen Funktionen aus
59
if (fall == 0) {
60
motor_stop();
61
}
62
63
else if (fall == 1) {
64
motor_rechts();
65
}
66
67
else if (fall == 2) {
68
motor_links();
69
}
70
71
else if (fall == 3) {
72
if (fahrt_rechts == 1)
73
{
74
motor_rechts();
75
if (digitalRead(PIN_Ende_rechts) == 0)
76
{
77
Serial.println("Ende rechts");
78
motor_stop();
79
fahrt_rechts = 0;
80
fahrt_links = 1;
81
}
82
}//fahrt_rechts
83
84
if (fahrt_links == 1)
85
{
86
motor_links();
87
if (digitalRead(PIN_Ende_links) == 0)
88
{
89
Serial.println("Ende links");
90
motor_stop();
91
fahrt_links = 0;
92
fahrt_rechts = 1;
93
}
94
} // fahrt_links
95
} // Fall 3
96
97
// // // // // // HTML erzeugen
98
client.flush();
99
String s = "HTTP/1.1 200 OK\r\n";
100
s += "Content-Type: text/html\r\n\r\n";
101
s += "<!DOCTYPE HTML>\r\n<html><center><H1>\r\n";
102
s += "</br></br>";
103
104
xxxxxxxxxxxxxx
105
106
107
s += "</H1></center></html>\n";
108
client.print(s);
109
delay(1);
110
111
} // Loop
112
113
// // // // // // Funktionen
114
void motor_stop()
115
{
116
Serial.println("Motor stop");
117
digitalWrite(PIN_Motor_rechts, LOW);
118
digitalWrite(PIN_Motor_links, LOW);
119
delay(500);
120
}
121
122
void motor_rechts()
123
{
124
Serial.println("Motor rechts");
125
digitalWrite(PIN_Motor_rechts, HIGH);
126
digitalWrite(PIN_Motor_links, LOW);
127
}
128
129
void motor_links()
130
{
131
Serial.println("Motor links");
132
digitalWrite(PIN_Motor_rechts, LOW);
133
digitalWrite(PIN_Motor_links, HIGH);
134
}
Kritik ist immer gerne gesehen.
Ach ja, die Loopzeit beträgt 500ms,
aber die Lichtschranken reagieren deutlich schneller.
Woran könnte das liegen?
Anmerkung:
Was soll das denn???
In dem durch xxxxxxx ersetzten Teil stand der Quelltext für HTML-Links.
Denn kann ich aber nicht absenden, weil die Forensoftware das als Spam
einordnet.
Kurt schrieb:> In dem durch xxxxxxx ersetzten Teil stand der Quelltext für HTML-Links.> Denn kann ich aber nicht absenden, weil die Forensoftware das als Spam> einordnet.
Das stört mich auch schon lange, das ist ein grundlegendes Problem der
Forensoftware. Da die Links eigentlich von der Forensoftware escaped
werden, macht diese Überprüfung in der Forensoftware eigentlich wenig
Sinn. Der Forenbetreiber scheint jedoch keine Zeit oder keine Lust zu
haben, dies zu Ändern.