Forum: Mikrocontroller und Digitale Elektronik Leichte Probleme mit Arduino Webserver und HTML-Implementierung


von Christian M. (christian_m280)


Angehängte Dateien:

Lesenswert?

Hallo Foraner,

habe mit Arduino Mega 2560 und Ethernet-Shield einen Webserver nach 
https://werner.rothschopf.net/202001_arduino_webserver_post.htm 
aufgesetzt. Darauf läuft auch die Steuerung der Heizung, funktioniert, 
habe ich aber rausgenommen, um das Problem zu zeigen:

In Zeile 205 habe ich einen Button um den Inhalt von 2 EEPROMs 
runterzuladen, hier ist vereinfacht einfach zwei verschachtelte 
Schleifen (Zeile 359...377) die die 256kB senden. Problem: Danach 
startet der Arduino neu. Kann mal jemand drüberschauen, ob alles korrekt 
ist bezüglich Content-Typ, Disposition und Length. Die Daten werden über 
StreamLib https://github.com/jandrassy/StreamLibdownload gesendet.

Ausserdem habe ich ein Problem bei der HTML-Implementation von obigem 
Button plus eines Zweiten, der in der Tabelle in der gleichen Zelle 
steht. Man sieht das gut im index.html Zeile 35...42. Die Buttons werden 
nicht nebeneinander sondern übereinander angezeigt. Mit dem Workaround
[code]
"<form method='post' action='/' name='dL' style='float: left;'>"
[code]
statt
[code]
"<form method='post' action='/' name='dL'>"
[code]
werden Beide in einer Zeile dargestellt, der Linke allerdings 
linksbündig. Meine Tabelle ist unsichtbar, enthält noch viele andere 
Elemente, und funktioniert so. Mich würde es aber trotzdem 
interessieren, warum zwei Formen (ist das das Problem?) nicht in eine 
Zellenzeile.

Das beigefügte HTML ist der DL aus dem Browser. Der Code.. äh Sketch 
sollte auf jedem Arduino Mega mit installierter StreamLib und 
Ethernet-Shield funktionieren. Zeile 13 muss allerdings noch 
verkommentiert werden.

Vielen Dank

Gruss Chregu

von Harald K. (kirnbichler)


Lesenswert?

Der Fehler liegt in Zeile 372:
1
message.write(j)

> write() - a virtual member function - must be implemented in
> the derived class for a single character transmission to the designation.

Du willst stattdessen message.add() verwenden.

von Christian M. (christian_m280)


Lesenswert?

Danke Harald!

Leider: error: 'class BufferedPrint' has no member named 'add'

Und beim favicon funktionierts ja auch mit message.write(). Dort wird 
auch je ein single character gesendet, wie hier auch.

Gruss Chregu

von Harald K. (kirnbichler)


Lesenswert?

Christian M. schrieb:
> Leider: error: 'class BufferedPrint' has no member named 'add'

Dann zeig doch bitte mal, wo Du diese Klasse herhast. Auf der Webseite, 
die Du verlinkt hast, gibt es die Beschreibung, aus der ich zitiert 
habe.

von Christian M. (christian_m280)


Lesenswert?

Sorry, war eh falsch geschrieben:
https://github.com/jandrassy/StreamLib
https://werner.rothschopf.net/202001_arduino_webserver_post.htm
Aber weder auf der einen noch der anderen Seite finde ich das Zitat. 
Aber ich bin momentan überfordert, von virtuellen Funktionen habe ich 
keine Ahnung, das muss ich mir zuerst erarbeiten.
Darum liebe ich C/C++: Da kann man sich die Zeit voll mit der Syntax 
verdrödeln statt an der Lösung zu Arbeiten...

Gruss Chregu

von Daniel A. (daniel-a)


Lesenswert?

Christian M. schrieb:
> Mich würde es aber trotzdem
> interessieren, warum zwei Formen (ist das das Problem?) nicht in eine
> Zellenzeile.

Das liegt daran, das diese block Elemente per default "display: block;" 
haben.  Mit "form { display: inline-block; }" oder "form { display: 
inline; }" liegen die nebeneinander wenn sie platz haben.
https://developer.mozilla.org/en-US/docs/Web/CSS/display?retiredLocale=de

Man könnte die Buttons auch in die selbe Form tun.
Oder üblicher wäre, ein Link < a > zu nehmen, und wie einen Button 
aussehen zu lassen. (Schau dir da eventuell auch das target= attribut 
an).

von J. S. (jojos)


Lesenswert?

Die virtuelle Funktion write() ist kein Problem, die ist ja in 
BufferedClient.cpp definiert. Sie könnte überschrieben werden, muss man 
aber nicht. Wäre sie nicht definiert, dann hättest du Compilerfehler 
bekommen.
Ich vermute das eher der Speicher knapp wird, wieviel RAM wird denn 
gebraucht, also in der Ausgabe nach dem kompilieren? Das ist schon mal 
das RAM was für alles globale gebraucht wird, dann kommt noch dynamisch 
allozierter und Stack dazu. Stack sind durch die Buffer die da liegen 
schon >200 Byte, der kann in den Heap wachsen und dann knallts.

von Christian M. (christian_m280)


Lesenswert?

J. S. schrieb:
> Ich vermute das eher der Speicher knapp wird, wieviel RAM wird denn
> gebraucht, also in der Ausgabe nach dem kompilieren?

Also dieses vereinfachte Beispiel, das ja auch abstürzt:
1
Globale Variablen verwenden 541 Bytes (6%) des dynamischen Speichers, 7651 Bytes für lokale Variablen verbleiben. Das Maximum sind 8192 Bytes.

Gruss Chregu

von J. S. (jojos)


Lesenswert?

ok, auch wenn man jetzt nicht weiß wie viel RAM da dynamisch gebraucht 
wird, das sollte locker reichen.
Die Webbrowser versuchen ja mehrere Verbindungen parallel zu öffnen, 
kann das ein Problem sein? Oder nur wenn versucht wird die EEPROM Daten 
zu übertragen?

edit:
Endlosschleifen laufen halt endlos...
1
for (byte j = 0; j < 256; j++) {

: Bearbeitet durch User
von Sebastian W. (wangnick)


Lesenswert?

Christian M. schrieb:
> In Zeile 205 habe ich einen Button um den Inhalt von 2 EEPROMs
> runterzuladen, hier ist vereinfacht einfach zwei verschachtelte
> Schleifen (Zeile 359...377) die die 256kB senden. Problem: Danach
> startet der Arduino neu.

Du schreibst über message.write() ohne den Rückgabewert zu überprüfen.

Christian M. schrieb:
> https://github.com/jandrassy/StreamLib

Schau die mal unter 
https://github.com/JAndrassy/StreamLib/blob/44589760c5367a614547b35edb75451bf72890cc/src/BufferedPrint.cpp#L31 
BufferedPrint::write und BufferedPrint::flush an.

Wenn BufferedPrint::write das letzte Zeichen in buffer geschrieben hat 
wird pos==size und flush() wird gerufen. Und wenn dort in 
BufferedPrint::flush bei target.write(buffer,pos) der EthernetClient 
nichts schreiben kann (was bei dir vorkommen wird weil die Hardware mit 
deinen vielen Daten überfordert ist) und daher 0 zurückgibt, dann wird 
l=0, und dann bleibt pos==size. Und wenn du dann das nächste Zeichen 
über BufferedPrint::write schreibst, dann wird das Zeichen HINTER das 
Ende von buffer geschrieben (weil pos==size) und dann wird pos zu size+1 
erhöht, und dann wird nie mehr flush() aufgerufen sondern fleißig weiter 
hinter buffer der Stack zerstört.

Das ist mMn ein Bug der https://github.com/JAndrassy/StreamLib.

LG, Sebastian

PS:
J. S. schrieb:
> Endlosschleifen laufen halt endlos...for (byte j = 0; j < 256; j++) {

Oh, das ist noch viel schlimmer ...

: Bearbeitet durch User
von Sebastian W. (wangnick)


Lesenswert?

Sebastian W. schrieb:
> der EthernetClient
> nichts schreiben kann (was bei dir vorkommen wird weil die Hardware mit
> deinen vielen Daten überfordert ist) und daher 0 zurückgibt

Das scheint nur zu passieren wenn der Socket unerwartet geschlossen 
wird. Ansonsten blockiert der EthernetClient bis die Daten geschrieben 
sind. Das ist also eher nicht dein Problem.

LG, Sebastian

von Christian M. (christian_m280)


Lesenswert?

J. S. schrieb:
> Endlosschleifen laufen halt endlos...for (byte j = 0; j < 256; j++) {

Uiuiui, jetzt seh' ich's auch... Lustigerweise bekomme ich genau die 
256kB Daten richtig. In der Anwendung mit dem EEPROM steht aber korrekt:
1
for (unsigned long i = 0; i < 16384; i++) {

Gruss Chregu

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
Noch kein Account? Hier anmelden.