Hallo an alle, ich experimentiere seid Tagen an einer Lösung und finde den Fehler nicht. Habe auf einem ESP32 mit Display (WIFI Kit 32 ESP32 WIFI drahtlos mit 0,96 Zoll OLED Display CP2102 Entwicklungsboard für Arduino Nodemcu) eine Stoppuhr am laufen. Das fktn einwandfrei allein. Nun wollte ich einen Webserver mit dem man versch. Pins steuern kann drauf packen. Das fktn aber NUR wenn ich den loop der Stoppuhr auskommentiere. Sind beide loops aktiv fktn nur die Stoppuhr auf dem Display und auch seriel, der Webserver ist dann nicht erreichbar. Könnte sich jemand bitte mal den Code anschauen und evtl. Ursachen feststellen? Hinweis: Der Webserver ist nur ein Zwischenschritt. Die fertige Lösung soll so fktn dass 3 ESP32 an denen Lichtschranken fungieren - Pins am Stoppuhren-ESP32 steuern und somit die Zeitmessung starten/stoppen. Falls jemand eine noch schlankere Lösung weiß, bitte vorschlagen. Zunächst wüsste ich eben nur gern, warum die jetzige Konstellation nicht fktn. VG Hardy
:
Bearbeitet durch User
> [..] fktn [..] versch. [..] fktn [..] fktn [..] Könnte sich jemand bitte > mal den Code anschauen und evtl. Ursachen feststellen? [..] > fktn [..] fktn. Klar, dzu mst d in br e hdn.
Hardy N. schrieb: > g457 schrieb: >> Klar, dzu mst d in br e hdn. > > Was willst Du mir damit sagen? Vermutlich, dass sich dein Text ziemlich blöd liest.
Belgacom schrieb: > Hardy N. schrieb: >> g457 schrieb: >>> Klar, dzu mst d in br e hdn. >> >> Was willst Du mir damit sagen? > > Vermutlich, dass sich dein Text ziemlich blöd liest. ..weil ich funktioniert abgekürzt habe??? Du bist aber seltsam drauf.
... du must delay unblocked implementieren! mt beispiel: //usage: // WAITBLOCK(MSEC,T2B,100) {digitalWrite(LED_PIN, digitalRead(LED_PIN)^1); //...} //fast flashed led //options #define USEC micros() //timer tick base #define MSEC millis() #define T2B uint16_t //timer data type #define T4B uint32_t //create an unique name from given parameter and line number #define UNIQUE(name) (name ## _LINE_) //creates an unique timer for each instance #define WAITBLOCK(tb, dt, t) \ static dt UNIQUE(tmr) = (dt) tb; \ if (tb - UNIQUE(tmr) >= t)
:
Bearbeitet durch User
Hardy N. schrieb: > ..weil ich funktioniert abgekürzt habe??? ja aber nun gut delay(1000); wenn in einer Funktion sinnlose Wartezeit vertrödelt wird, wie kommst du darauf das andere Funktionen noch funktionieren? statt sinnlos delay(1000); zu vertrödeln könnte ja den anderen Aufgaben nachgegangenen werden, z.B. auf dem Webserver. Also besser programmieren lernen.
:
Bearbeitet durch User
Dein Problem ist ein strukturelles:
1 | while (client.connected()) { |
2 | ...
|
3 | }
|
4 | |
5 | while (digitalRead(0) == HIGH) { |
6 | ...
|
7 | }
|
Diese beiden Stellen blockieren den Programmablauf. Das Arduino Framework unterstützt die Entwicklung von Multi-Taskin mit der Methode der Endlichen Automaten (Zustandautomaten). Das Prinzip wird hier anhand eines fiktiven C Programm erklärt: http://stefanfrings.de/net_io/protosockets.html (für dich ist nur der Absatz "Zustandsautomat" relevant). Ein konkretes Beispiel findest du in dem Buch http://stefanfrings.de/mikrocontroller_buch/Einstieg%20in%20die%20Elektronik%20mit%20Mikrocontrollern%20-%20Band%203.pdf Kapitel 9. Dann ist mir noch aufgefallen, dass du viele relativ grosse Zeichenketten im RAM hast. Benutze PROGMEM, PSTR() und F() damit die Strings nur im Flash Speicher liegen, nicht im RAM. https://arduino-esp8266.readthedocs.io/en/latest/PROGMEM.html
Ok, hab alle Hinweise gelesen. Vielen Dank dafür erstmal. Ich bin wirklich ein kopletter Anfänger und war froh es bis hier geschafft zu haben. :-) Ich gucke erstmal, ob ich es mit Eurer Hilfe hinbekomme. Melde mich dann. VG
:
Bearbeitet durch User
Joachim B. schrieb: > aber nun gut > delay(1000); > > wenn in einer Funktion sinnlose Wartezeit vertrödelt wird, wie kommst du > darauf das andere Funktionen noch funktionieren? > > statt sinnlos delay(1000); zu vertrödeln könnte ja den anderen Aufgaben > nachgegangenen werden, z.B. auf dem Webserver. hab delay(1000); auskommentiert. daran liegt es nicht. danke aber für den Hinweis.
Apollo M. schrieb: > ... du must delay unblocked implementieren! > > mt > > beispiel: > > //usage: > // WAITBLOCK(MSEC,T2B,100) {digitalWrite(LED_PIN, > digitalRead(LED_PIN)^1); //...} //fast flashed led > > //options > #define USEC micros() //timer tick base > #define MSEC millis() > #define T2B uint16_t //timer data type > #define T4B uint32_t > > //create an unique name from given parameter and line number > #define UNIQUE(name) (name ## LINE) > > //creates an unique timer for each instance > #define WAITBLOCK(tb, dt, t) \ > static dt UNIQUE(tmr) = (dt) tb; \ > if (tb - UNIQUE(tmr) >= t) da stehe ich komplett auf dem Schlauch... Dafür reicht mein Verständnis noch nicht aus. Da muss ich erstmal lesen... Vielen Dank für den Hinweis.
Stefanus F. schrieb: > Dein Problem ist ein strukturelles:while (client.connected()) { > ... > } > > while (digitalRead(0) == HIGH) { > ... > } Vielen Dank auch Dir. Ich lese mich da mal ein und teste dann mal etwas... Eine Frage, Du hast bestimmt auch die anderen Hinweise gelesen: Bevor ich mich nun um die Themen kümmere, was sagst Du zum Hinweis von: Apollo M. schrieb: > ... du must delay unblocked implementieren! Weil, wenn ich erstmal grob weiß, woran es liegt, bin ich auch gern bereit mir die nacht um die Ohren zu schlagen. Will eben, wenns geht, aber gleich das "richtige" Thema angehen. ...kann natürlich aucch sein, dass beides Einfluss auch den/die Fehler hat. VG Hardy
Hardy N. schrieb: > Belgacom schrieb: >> Hardy N. schrieb: >>> g457 schrieb: >>>> Klar, dzu mst d in br e hdn. >>> >>> Was willst Du mir damit sagen? >> >> Vermutlich, dass sich dein Text ziemlich blöd liest. > > ..weil ich funktioniert abgekürzt habe??? > > Du bist aber seltsam drauf. Ich nicht, sondern Du. Du hast den Text geschrieben.
Belgacom schrieb: > Hardy N. schrieb: >> Belgacom schrieb: >>> Hardy N. schrieb: >>>> g457 schrieb: >>>>> Klar, dzu mst d in br e hdn. >>>> >>>> Was willst Du mir damit sagen? >>> >>> Vermutlich, dass sich dein Text ziemlich blöd liest. >> >> ..weil ich funktioniert abgekürzt habe??? >> >> Du bist aber seltsam drauf. > > Ich nicht, sondern Du. Du hast den Text geschrieben. Ich verstehe nur eins nicht: Warum meldest Du Dich überhaupt, wenn Du mit meinem Text oder Abkürzungen Probleme hast? Brauchst Dich doch gar nicht melden und meinen Beitrag ignorieren! Das kostet uns beiden doch nur unnötig Zeit. Im Übrigen haben andere auf meinen Thread trotz der Abkürzungen geantwortet. Ich wünsche Dir ein schönes WE! (WE- Wochenende)
Hardy N. schrieb: > da stehe ich komplett auf dem Schlauch... Kein Wunder, für meinen Geschmack ist das zu viel Makro-Magie. Der Adam Dunkels hatte etwas ähnliches mit seinen Protothreads veranstaltet, die gefallen mir auch nicht. Ich gebe Dir mal ein entzaubertes Beispiel:
1 | #define LED_ROT 2
|
2 | #define LED_GELB 3
|
3 | #define LED_GRUEN 4
|
4 | |
5 | void setup() |
6 | {
|
7 | pinMode(LED_ROT,OUTPUT); |
8 | pinMode(LED_GELB,OUTPUT); |
9 | pinMode(LED_GRUEN,OUTPUT); |
10 | }
|
11 | |
12 | void thread_rot() |
13 | {
|
14 | static enum {AUS, WARTE_AUS, EIN, WARTE_EIN} state=AUS; |
15 | static unsigned long warteSeit; |
16 | switch (state) |
17 | {
|
18 | case AUS: |
19 | digitalWrite(LED_ROT,LOW); |
20 | warteSeit=millis(); |
21 | state=WARTE_AUS; |
22 | break; |
23 | |
24 | case WARTE_AUS: |
25 | if (warteSeit-millis() >= 100) // wenn 100ms verstrichen sind |
26 | {
|
27 | state=EIN; |
28 | }
|
29 | break; |
30 | |
31 | case EIN: |
32 | digitalWrite(LED_ROT,HIGH); |
33 | warteSeit=millis(); |
34 | state=WARTE_EIN; |
35 | break; |
36 | |
37 | case WARTE_EIN: |
38 | if (warteSeit-millis() >= 100) // wenn 100ms verstrichen sind |
39 | {
|
40 | state=AUS; |
41 | }
|
42 | break; |
43 | }
|
44 | }
|
45 | |
46 | void thread_gelb() |
47 | {
|
48 | // genau der gleiche Code wie für die rote LED, aber mit 250ms.
|
49 | }
|
50 | |
51 | void thread_gruen() |
52 | {
|
53 | // genau der gleiche Code wie für die rote LED, aber mit 400ms.
|
54 | }
|
55 | |
56 | void loop() |
57 | {
|
58 | thread_rot(); |
59 | thread_gelb(); |
60 | thread_gruen(); |
61 | }
|
Alle drei Threads blockieren den Programmablauf nicht. Sie hängen nicht in Warteschleifen fest, sondern beenden sich bei jedem Aufruf direkt wieder. Das Schlüsselwort "static" vor den lokalen Variablen sorgt dafür, dass sie ihren Wert zwischen mehreren Funktionsaufrufen nicht vergessen. Beim ersten Aufruf ist der Thread im Status "AUS". In diesem Schritt wird die LED aus geschaltet und dann die aktuelle Zeit in der Variable warteSeit gespeichert. Dann wird zum nächsten Status "WARTE_AUS" weiter geschaltet. Beim zweiten Aufruf ist der Thread im Status "WARTE_AUS". In diesem Schritt wird geprüft, ob die gewünschte Wartezeit erreicht (oder gar überschritten) wurde. Wenn das der Fall ist, wird auf den nächsten Status "EIN" weiter geschaltet. Beim dritten Aufruf wurde die gewünschte Zeit noch nicht erreicht, daher bleibt der Thread im Status "WARTE_AUS". Beim vierten Aufruf wurde die gewünschte Zeit noch nicht erreicht, daher bleibt der Thread im Status "WARTE_AUS". Beim fünften Aufruf wurde die gewünschte Zeit noch nicht erreicht, daher bleibt der Thread im Status "WARTE_AUS". ... Irgendwann ist es dann so weit, der Status wechselt nach "EIN". Beim darauf folgenden Aufruf wird die LED eingeschaltet. Danach wird erneut gewartet. Der entscheidende Trick ist, dass die Thread-Funktion niemals hängen bleibt. Jeder einzelne Aufruf dauert nur wenige Mikrosekunden. In der Hauptschleife loop() kannst du daher sehr viele solcher Threads aufrufen. Es sieht von aussen betrachtet so aus, als ob sie gleichzeitig laufen würden. Bei der Abfrage der verstrichenen Zeit ist es wichtig, dass die Variable (warteSeit) den gleichen Typ hat, wie der Rückgabewert von millis() und dass man die Differenz mit einer Subtraktion bildet. Diese Methode funktioniert sogar korrekt, wenn der Zeit-Zähler von seinem Maximal-Wert auf 0 über läuft. Bei allen anderen Methoden, die auf Addition beruhen, klappt das nicht.
Stefanus F. schrieb: > Hardy N. schrieb: >> da stehe ich komplett auf dem Schlauch... > > Kein Wunder, für meinen Geschmack ist das zu viel Makro-Magie. Der Adam > Dunkels hatte etwas ähnliches mit seinen Protothreads veranstaltet, die > gefallen mir auch nicht. > > Ich gebe Dir mal ein entzaubertes Beispiel: Ok. Ich versuche mal Dein Beispiel auf meinem Sketch anzuwenden. Wird allerdings sicher etwas dauern...:-) Danke für Deine Mühe!
Hardy N. schrieb: > Wird allerdings sicher etwas dauern. Ja, es erfordert eine erhebliche Änderung deiner Programmstruktur. Aber wenn du den Dreh einmal raus hast, kannst du es beliebig erweitern.
... noch zwei macros mehr, für die werte leserschaft und jene die noch was dazu lernen wollen oder mal grübeln wollen was alles in c so geht! der vorteil dieser macros ist vorallem, dass eine beliebige anzahl von "instancen" erzeugt werden können, sprich jedes macro erzeugt einen neuen unabhängigen timer und als beispiel zur anwendung von "k-logic" in c. mt WAITBLOCK = nonblocking wait PERIODIC = nonblocking periodic instruction block XPERIODIC = nonblocking x-time repeating instruction block // WAITBLOCK(MSEC,T2B,100) {digitalWrite(LED_PIN, digitalRead(LED_PIN)^1); //...} //fast flashed led // PERIODIC(MSEC,T2B,500) {digitalWrite(LED_PIN, digitalRead(LED_PIN)^1); //...} //blinky led // XPERIODIC(MSEC,T2B,500,42) {digitalWrite(LED_PIN, digitalRead(LED_PIN)^1); //...} //42-times blinky led //options #define USEC micros() //timer tick base #define MSEC millis() #define T2B uint16_t //timer data type #define T4B uint32_t //create an unique name from given parameter and line number #define UNIQUE(name) (name ## _LINE_) //creates an unique timer for each instance #define WAITBLOCK(tb, dt, t) \ static dt UNIQUE(tmr) = (dt) tb; \ if (tb - UNIQUE(tmr) >= t) //creates an unique timer for each instance #define PERIODIC(tb, dt, t) \ static dt UNIQUE(tmr) = (dt) tb; \ if ((tb - UNIQUE(tmr) >= t) \ && (UNIQUE(tmr) = tb, 1)) //(UNIQUE(tmr) += t, 1)) //creates an unique timer for each instance, x: repeats 1-255 #define XPERIODIC(tb, dt, t, x) \ static dt UNIQUE(tmr) = (dt) tb; \ static uint8_t UNIQUE(xRepeats) = x; \ if ((tb - UNIQUE(tmr) >= t) \ && UNIQUE(xRepeats) \ && (UNIQUE(xRepeats)--, UNIQUE(tmr) = tb, 1)) //UNIQUE(tmr) += t, 1))
Apollo M. schrieb: > noch zwei macros mehr Also ich habe mal gelernt, dass Quelltext für andere Entwickler gut lesbar sein soll. Das ist deiner ganz sicher nicht. Damit setzt du Dir selbst ein unrühmliches Denkmal. Deine Nachfolger werden diesen Code hassen. Also wenn ich den Job wechsle, möchte ich nicht, dass mein alter Chef dem neuen erzählt "Wir sind froh, dass der Stefanus weg ist, denn was der fabriziert hat ist langfristig betrachtet unwartbarer Code - ein geschäftliches Risiko.".
Stefanus F. schrieb: > Das Prinzip wird hier anhand eines fiktiven C Programm erklärt: > http://stefanfrings.de/net_io/protosockets.html (für dich ist nur der > Absatz "Zustandsautomat" relevant). ich kann zu protothreads noch das darauf basierende cocoOS rtos empfehlen, very small footprint, simple, und läuft bei mir auf pic16/18, avr, stm, arm oder auch auf jeden host. http://www.cocoos.net der stefan hat unter dem link mit viel mühe alles schön erklärt! mt
Stefanus F. schrieb: > Deine Nachfolger werden diesen Code > hassen. ... kommt auf das niveau an, dass ist schlicht nur eine liga höher. die macros stehen in einem header und der aufruf ist simple kurz und klar! hast du schon mal tiefer in die gcc lib macros geschaut? da sind diese hier nur basic. mt
Apollo M. schrieb: > der stefan hat unter dem link mit viel mühe alles schön erklärt! Danke, aber ich mag die Protothreads trotzdem nicht. Da passiert mir zu viel unsichtbares im Hintergrund (Makro-Magie).
Stefanus F. schrieb: > Danke, aber ich mag die Protothreads trotzdem nicht. Da passiert mir zu > viel unsichtbares im Hintergrund (Makro-Magie). ich habe auch länger gebraucht bis ich mit protothreads warm geworden bin :-) aber hilfe! die sind überall in anwendung z.b. im linux kernel oder micro python moduls. halt immer dann, wenn es um nonblocking protocols and small overhead geht. ich bin gerade richtig begeistert von cocoos, give it a trail! mt
:
Bearbeitet durch User
Stefanus F. schrieb: > Dann ist mir noch aufgefallen, dass du viele relativ grosse > Zeichenketten im RAM hast. Benutze PROGMEM, PSTR() und F() damit die > Strings nur im Flash Speicher liegen, nicht im RAM. > https://arduino-esp8266.readthedocs.io/en/latest/PROGMEM.html Das sollte beim ESP32 doch eigentlich egal sein, da dieser anders aufgebaut ist als z.B. AVR Controller. Wenn ich mich richtig erinnere werden die von dir genannten Marcos durch das Framework einfach "elemeniert". Ansonsten kann man beim ESP32 auch ganz einfach mit echten FreeRTOS Threads arbeiten und so mehrere Dinge wirklich parallel machen. Dafür hat man dann andere "Problem" um die man sich kümmern muss.
Mike R. schrieb: > Wenn ich mich richtig erinnere werden die von dir genannten > Makros durch das Framework einfach "elemeniert". Ja, das scheint zu stimmen - wusste ich noch nicht. Beim ESP8266 sind diese Makros keine Dummies.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.