Forum: Mikrocontroller und Digitale Elektronik Arduino variable verstehen und löschen.


von Genesüß (Gast)


Lesenswert?

Hallo
Ich möchte in Arduino die Bibliothek Json Serialisizer verwenden.
Ich bin noch absoluter Anfänger und verstehe nicht mit welcher Art 
Variablen die da arbeiten.

Also im Code wird die Variable mit StaticJsonDocument<200> doc; 
angelegt.
Max 200 byte und der name ist doc
gefüllt wird das ding mit
  doc["id"] = 0;
  doc["temp"] = sensor.getTempC();

und mit serializeJsonPretty(doc, Serial);
wird es auf die serielle schnitstelle gesendet.

Was ist das für eine art variable? ein String arry?
Und wie löscht man das wieder?

von Johannes S. (Gast)


Lesenswert?

Das ist eine Template Klasse. Wenn die als static angelegt wird, dann 
kann man die nicht ‚löschen‘. Das geht nur bei dynamisch mit new 
angelegten Instanzen.

von Genesüß (Gast)


Lesenswert?

Aber wie würde man " doc["id"] = 0;" zb wieder loswerden? wenn man 
danach ein json ohne id senden möchte? Einfach ein neues anlegen? Dann 
bleibt id und der rest ja im Speicher

von MaWin (Gast)


Lesenswert?

Genesüß schrieb:

> Was ist das für eine art variable? ein String arry?
> Und wie löscht man das wieder?

Du kannst nur bis 10min nach Beitragserstellung als angemeldeter Nutzer 
den Beitrag bearbeiten. Solange hast du Zeit diese Zeile zu löschen. 
Ohne Anmeldung muss das ein Moderator für dich übernehmen.

von Johannes S. (Gast)


Lesenswert?

Dazu muss man in die Doku der Klasse nachsehen, die sollte dann sowas 
wie eine init() oder clear() Methode haben.

von Rolf M. (rmagnus)


Lesenswert?

Genesüß schrieb:
> Aber wie würde man " doc["id"] = 0;" zb wieder loswerden? wenn man
> danach ein json ohne id senden möchte? Einfach ein neues anlegen? Dann
> bleibt id und der rest ja im Speicher

Laut Doku benutzt man dafür die Memberfunktion remove(). Oder clear(), 
wenn man alles löschen will.

von Peter D. (peda)


Lesenswert?

Welche Aufgabe willst Du denn mit Java auf dem Arduino lösen und auf 
welchem?

Es ist immer schwierig, wenn Fragen zu allgemein gehalten werden und 
niemand erraten kann, was eigentlich Dein Problem ist.
Ich hab noch in keinem einzigen Programm Variablen "gelöscht".

von Einer K. (Gast)


Lesenswert?

Peter D. schrieb:
> Welche Aufgabe willst Du denn mit Java auf dem Arduino .... ?
Scheinbar keine!
Json == JavaScript Object Notation

Ein weit verbreitetes Datenaustauschformat zwischen unterschiedlichsten 
Maschinen bzw. zwischen Server und Client.
Schlanker, als XML (und damit besser für µC geeignet)
Es hat sich längst verselbstständigt, von JavaScript gelöst.
Für jede Sprache mit Rang und Namen, gibts mittlerweile JSON Libs.

Und ja, da man nicht immer die gleichen Daten versenden will, muss man 
auch mal in den vorbereiteten Datenblöcken rumlöschen.

von Peter D. (peda)


Lesenswert?

Arduino Fanboy D. schrieb:
> Und ja, da man nicht immer die gleichen Daten versenden will, muss man
> auch mal in den vorbereiteten Datenblöcken rumlöschen.

Muß man nicht. Man kann z.B. mit sprintf einen konstanten Formatstring 
ausgeben und dann nur die Platzhalter durch die aktuellen Parameter 
ersetzen lassen.

Die Frage bleibt natürlich weiterhin, was will man mit Json auf einem MC 
erreichen?
Mir erschließt sich die Anwendung nicht. Gerade für einen Anfänger.

Ich vermute aber mal, daß die klassischen AVR Arduinos zu schwachbrüstig 
sein werden und es daher um die 32Bit Boliden geht. Daher sollte man 
besser den konkreten Typ nennen. Einfach nur Arduino verleitet doch zu 
Mißverständnissen.

von Christian H. (netzwanze) Benutzerseite


Lesenswert?

Meinst Du diese Bibliothek? https://arduinojson.org/

Dann geht es damit:
https://arduinojson.org/v6/api/jsondocument/clear/

Oder, laut Doku, auch mit der Funktion:
remove() removes an element (or member) at the specified index (or key)

von Einer K. (Gast)


Lesenswert?

Peter D. schrieb:
> Ich vermute aber mal, daß die klassischen AVR Arduinos zu schwachbrüstig
> sein werden

In dem Fall wird halt 200 Byte Ram reserviert.
Somit hat erstmal kein einziger AVR Arduino ein grundsätzliches Problem 
damit.
Die großen, schon mal gar nicht.


Ich glaube nicht, dass man die Sinnhaftigkeit eines (nahezu)weltweit, in 
(nahezu)allen Sprache, auf (nahezu)allen Maschinen nutzbaren Datenformat 
in Frage stellen sollte.
In (nahezu)allen Belangen ist eine solche Lösung, einem proprietärem 
Format eines Anfängers, überlegen.
Ein geübter Parser-/Generatorbauer wird evtl. was schlankeres bauen 
können.
Aber für Anfänger ist JSON genau das richtige.
Schlank und seit langer Zeit bewährt.

Peter D. schrieb:
> Die Frage bleibt natürlich weiterhin, was will man mit Json auf einem MC
> erreichen?
Kommunikation mit anderen Geräten.
Das ist halt der Sinn und Zwecke eines quasi standardisiertem 
Datenaustauschformates.

von pnp (Gast)


Lesenswert?

MaWin schrieb:
> Ohne Anmeldung muss das ein Moderator für dich übernehmen.

Du meinst also, dass ein Moderator die Klasse beim Arduino des TO 
löschen muss? ;-)

von Peter D. (peda)


Lesenswert?

Christian H. schrieb:
> Oder, laut Doku, auch mit der Funktion:
> remove() removes an element (or member) at the specified index (or key)

Da steht aber auch:
"If you use the library as intended (see the examples and the book), you 
don’t need to call this function."

Daher meine Bemerkung, ich habe noch nie was aktiv löschen müssen.

von Oliver S. (oliverso)


Lesenswert?

Arduino Fanboy D. schrieb:
> Ich glaube nicht, dass man die Sinnhaftigkeit eines (nahezu)weltweit, in
> (nahezu)allen Sprache, auf (nahezu)allen Maschinen nutzbaren Datenformat
> in Frage stellen sollte.

Es ging wohl weniger darum, JSon in Frage zu stellen, als vielmehr das, 
was der TO damit vorhat.

Wenn es tatsächlich nur darum geht, ein paar Messdaten in (lesbaren?) 
Text zu verwandeln, dann stellt sich die Sinnfrage schon.

Die Frage, was das für eine Variable ist, und wie man die wieder löscht, 
beantwortet jedes C++-Buch zusammen mit einem Blick in den Sourcecode.

Oliver

von Peter D. (peda)


Lesenswert?

Arduino Fanboy D. schrieb:
> Kommunikation mit anderen Geräten.

Das ist mir schon klar, aber welche konkret.
Gerade Anfänger tun sich damit schwer und unterschätzen den Aufwand, 
eine zuverlässige und fehlertolerante Kommunikation zu implementieren.

von Einer K. (Gast)


Lesenswert?

Peter D. schrieb:
> Gerade Anfänger tun sich damit schwer und unterschätzen den Aufwand,
> eine zuverlässige und fehlertolerante Kommunikation zu implementieren.

Siehste...
Genau aus dem Grund ist JSON auch eine gar nicht so schlechte Wahl.
Zumindest wird davon ein Teilaspekt der Kommunikation abgedeckt.

Oliver S. schrieb:
> Die Frage, was das für eine Variable ist, und wie man die wieder löscht,
> beantwortet jedes C++-Buch zusammen mit einem Blick in den Sourcecode.
Hier habt ihr beide ein Problem mit den Begrifflichkeiten und ihrer 
Semantik.
Explizit wurde hier der Key "id" genannt, welcher mitsamt seinen Daten 
verschwinden soll, zwecks Recycling des Containers, für den nächsten 
Transfer. Ein C++ Buch hilft da nur bedingt, Z.B. um die Klassen Doku 
überhaupt verstehen/anwenden zu können.

Peter D. schrieb:
> Da steht aber auch:
> "If you use the library as intended (see the examples and the book), you
> don’t need to call this function."
>
> Daher meine Bemerkung, ich habe noch nie was aktiv löschen müssen.

Allerdings ist "intended", die nicht statische Variante, sondern die, 
welche ihre Daten auf dem Heap zusammenklöppelt.
Ihm verwendet allerdings: StaticJsonDocument<200>
Dessen Speicher verfällt erst, wenn der Geltungsbereich, in dem die 
Instanz angelegt wurde, verlassen wird.
Die Alternative: new und delete
Aber dann ist man wieder auf dem Heap, was man ja bei kleineren µC schon 
vermeiden sollte. Und ob die Zeigerwirtschaft was für Anfänger ist, naja 
....

Peter D. schrieb:
> Das ist mir schon klar, aber welche konkret.
Tja....
Vielleicht erfahren wir das noch....

von Peter D. (peda)


Lesenswert?

Arduino Fanboy D. schrieb:
> Genau aus dem Grund ist JSON auch eine gar nicht so schlechte Wahl.
> Zumindest wird davon ein Teilaspekt der Kommunikation abgedeckt.

Soweit ich das sehe, übernimmt es nur das Parsen einer korrekten 
Nachricht.
CRC, Retry usw. sind nicht beinhaltet. Dazu braucht man 
Übertragungsprotokolle (CAN, TCP/IP).

UART, I2C, SPI usw. sichern nichts ab. Je nach Protokoll kann eine 
gestörte Nachricht sogar viele folgende Nachrichten stören.

von Christian H. (netzwanze) Benutzerseite


Lesenswert?

Möchte man lediglich kurze JSON-Telegramme mit einigen Messdaten 
verschicken, geht das sicherlich auch ohne Bibliothek. Die ist nur 
erforderlich, wenn die Telegramme umfangreicher und stark dynamisch 
sind.

Komplizierter wird eher das Parsen oder gar die Prüfung gegen eine 
JSON-Schema.
Darauf würde ich aber verzichten, wenn die Struktur nicht falsch sein 
kann.

von Peter D. (peda)


Lesenswert?

Arduino Fanboy D. schrieb:
> Genau aus dem Grund ist JSON auch eine gar nicht so schlechte Wahl.

Ich habe allerdings den Eindruck, daß der Fragesteller mit so einem 
komplexen Werkzeug ziemlich überfordert ist. Was wie genau passiert, 
steht an vielen Stellen verteilt und ist daher schwer zu verfolgen.

Natürlich benötigen printf/scanf auch einige Zeit zum Einarbeiten. Ich 
mag daran, daß alles in einer Zeile passiert, also schön zu überblicken 
ist. Die Seite mit der Erklärung der Formatstrings kann man sich ja 
daneben legen.
Für printf/scanf mit float sollte man schon einen ATmega328 nehmen. Zu 
Fuß (strtok, atof) würde ich aber nicht mehr parsen wollen.

von Stefan F. (Gast)


Lesenswert?

Bei der Sprache Go kann man im printf-Pendant %v als Platzhalter für 
Variablen benutzen, sofern das Standard-Format passt. Der Datentyp wird 
automatisch erkannt. Das gefällt mir.

von Marc (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Bei der Sprache Go kann man im printf-Pendant %v als Platzhalter für
> Variablen benutzen

Was hat das mit dem Problem zu tun?
Das geht auch in C++: fmtlib. Müsste eigentlich auch auf Arduino 
funktionieren (nur so als Sidekick...)

von Stefan F. (Gast)


Lesenswert?

Marc schrieb:
> Was hat das mit dem Problem zu tun?

Es hat etwas mit direkt davor stehenden Beitrag von Peter D. zu tun.

von Marc (Gast)


Lesenswert?

An Genesüß:

Falls Du ohne clear auskommen willst, must Du den Bereich des Objektes 
einfach mittels Klammern eingrenzen.
Die existenz lokaler Variablen/Objekte endet, wenn der Block,in dem sie 
deklariert wurden, wieder verlassen wird.

1
void function123() 
2
{
3
   { // erstes json Objekt
4
   StaticJsonDocument<200> doc; 
5
   doc["id"] = 0;
6
   doc["temp"] = sensor.getTempC();
7
   deserializeJson(doc, json);
8
   //...
9
   } // Ende Lebenszeit json Objekt
10
   
11
   { // Zweites json Objekt wird geboren
12
   StaticJsonDocument<200> doc; 
13
   // jetzt ohne ID....
14
   doc["temp"] = sensor.getTempC();
15
   deserializeJson(doc, json);
16
   //...
17
   } // Ende Lebenszeit json Objekt
18
  
19
   
20
   //...
21
}

von Marc (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Marc schrieb:
>> Was hat das mit dem Problem zu tun?
> Es hat etwas mit direkt davor stehenden Beitrag von Peter D. zu tun.

Ah, sorry, jetzt versteh ich.

Für mich macht die arduino json Lib aber keinen schlechten Eindruck.

Der TO hat halt vermutlich noch prinzipielle Probleme
wie man die Lebenszeit von Objekte beeinflussen kann.

von Wolfgang (Gast)


Lesenswert?

Peter D. schrieb:
> Ich vermute aber mal, daß die klassischen AVR Arduinos zu schwachbrüstig
> sein werden ...

Muss ja nicht, könnte sich auch um einen Arduino Due handeln ;-)

von chris_ (Gast)


Lesenswert?

>Muss ja nicht, könnte sich auch um einen Arduino Due handeln ;-)

https://arduinojson.org/

Wenn man so unten auf die Webseite guckt, ist die Library wohl vor allem 
für IOT-Anwendungen mit dem ESP gedacht.

von Genesüß (Gast)


Lesenswert?

Oh hier ist ja richtig was los ;)
Etwas Aufklärung also mit .clear(); habe ich es gelöscht bekommen.
Löschen möchte ich es um je nach Situation nicht alle Variablen zu 
senden.
Ich erzeuge je nach Anzahl Daten ein Array.

So warum nehme ich eine fertige Bibliothek. Weil die von "Profis" 
gemacht wurde klein ist und funktioniert. Ich habe versucht einen Json 
Parser selber zu schreiben aber wo ich den soweit hatte war mein 328 
fast voll und die Leistung war echt nicht gut.
Die Bibliothek übernimmt auch das empfangen über Seriell und sortiert 
die werte sauber in variablen. Das finde ich richtig Praktisch. So liegt 
jetzt die Auslastung bei ca 40% des Flash

von Rolf M. (rmagnus)


Lesenswert?

Marc schrieb:
> An Genesüß:
>
> Falls Du ohne clear auskommen willst, must Du den Bereich des Objektes
> einfach mittels Klammern eingrenzen.
> Die existenz lokaler Variablen/Objekte endet, wenn der Block,in dem sie
> deklariert wurden, wieder verlassen wird.

Allerdings garantiert das nicht, dass der Speicher auch wieder frei 
wird. Soweit ich weiß, wird üblicherweise der gesamte Speicher für die 
lokalen Variablen beim Start der Funktion auf dem Stack belegt und 
bleibt das bis zur Rückkehr aus der Funktion. Da gilt auch für Variablen 
innerhalb solcher Blöcke. Das heißt, deine Beispielfunktion braucht 
während ihrer gesamten Laufzeit den Platz für beide Json-Dokumente.

von Peter D. (peda)


Lesenswert?

Genesüß schrieb:
> Ich habe versucht einen Json
> Parser selber zu schreiben aber wo ich den soweit hatte war mein 328
> fast voll und die Leistung war echt nicht gut.

Da würde mich mal interessieren, wozu Du den Json-Parser brauchst und 
wie dann der komplette Aufrufcode dazu aussieht.

Nur ein paar Meßwerte als Text zu übertragen, geht ja auch sehr einfach 
direkt mit printf/scanf, da muß man nichts kompliziert parsen.

von Marc (Gast)


Lesenswert?

Rolf M. schrieb:
> Allerdings garantiert das nicht, dass der Speicher auch wieder frei
> wird. Soweit ich weiß, wird üblicherweise der gesamte Speicher für die
> lokalen Variablen beim Start der Funktion auf dem Stack belegt und
> bleibt das bis zur Rückkehr aus der Funktion.

Ich bin davon ausgegangen, dass "StaticJsonDocument" nur Stack Speicher 
nutzt und der Compiler es korrekt umsetzt.

Siehe https://arduinojson.org/v6/api/staticjsondocument/

>StaticJsonDocument is a JsonDocument that allocates its memory pool in-place, so 
it doesn’t rely on dynamic memory allocation.

Ein kurzer Test mit einem kleinen Arduino zeigt bei mir zumindest mein 
angenommenes Verhalten: lokale Variablen belegen nur innerhalb ihrer 
Lebensdauer Stackspeicher.
Das habe ich schon bei verschiedenen kleinen Embedded Controller genutzt 
und hat funktioniert. Das würde IMHO auch meinem Verständnis von C++ 
ctor/dtor widersprechen.

von Einer K. (Gast)


Lesenswert?

Marc schrieb:
> Ich bin davon ausgegangen, dass "StaticJsonDocument" nur Stack Speicher
> nutzt und der Compiler es korrekt umsetzt.

Wenn "StaticJsonDocument" als lokale Instanz angelegt wird, liegt es 
vollständig auf dem Stack.
Das ist richtig!

Angelegt im globalen Namensraum, liegt es neben den anderen 
initialisierten Variablen und auch statischen lokalen Variablen, in der 
gleichen Daten Sektion.

Was einem aber auch keiner verwehren kann, ist die Erzeugung per new.
Dann landet es auf dem Heap.

In allen diese Fällen, ändert sich nicht der Speicherverbrauch im Laufe 
der Lebenszeit der Instanz.
Das ist das "Statische" in "StaticJsonDocument"

von Marc (Gast)


Lesenswert?

Marc schrieb:
> Das würde IMHO auch meinem Verständnis von C++ ctor/dtor widersprechen.

Sollte natürlich heissen:
>Das würde IMHO auch meinem Verständnis von C++ ctor/dtor entsprechen.

von Rolf M. (rmagnus)


Lesenswert?

Marc schrieb:
> Rolf M. schrieb:
>> Allerdings garantiert das nicht, dass der Speicher auch wieder frei
>> wird. Soweit ich weiß, wird üblicherweise der gesamte Speicher für die
>> lokalen Variablen beim Start der Funktion auf dem Stack belegt und
>> bleibt das bis zur Rückkehr aus der Funktion.
>
> Ich bin davon ausgegangen, dass "StaticJsonDocument" nur Stack Speicher
> nutzt und der Compiler es korrekt umsetzt.

Ich auch.

> Ein kurzer Test mit einem kleinen Arduino zeigt bei mir zumindest mein
> angenommenes Verhalten: lokale Variablen belegen nur innerhalb ihrer
> Lebensdauer Stackspeicher.

Das kann ich nicht bestätigen. Der Speicher wird allerdings 
wiederverwendet, d.h. die Variablen aus dem ersten und dem zweiten Block 
nutzen den selben Speicherbereich, aber dieser wird bei mir bereits bei 
Beginn im Prolog der Funktion belegt und erst am Schluss vor dem 
Rücksprung wieder freigegeben. Und er wird z.B. auch belegt, wenn die 
Variable in einem if steht, aber dieser Zweig gar nicht zur Ausführung 
kommt.

> Das habe ich schon bei verschiedenen kleinen Embedded Controller genutzt
> und hat funktioniert. Das würde IMHO auch meinem Verständnis von C++
> ctor/dtor widersprechen.

Was hat das mit Konstruktoren zu tun? Es geht darum, dass der Speicher 
erst wieder nach Rückkehr aus der Funktion verfügbar wird. Konstruktor 
und Destruktor werden selbstverständlich korrekt aufgerufen.

von Marc (Gast)


Lesenswert?

Rolf M. schrieb:
> Was hat das mit Konstruktoren zu tun? Es geht darum, dass der Speicher
> erst wieder nach Rückkehr aus der Funktion verfügbar wird. Konstruktor
> und Destruktor werden selbstverständlich korrekt aufgerufen.

Hast recht, nicht viel.

Eine Erklärung warum ggf am Ende der Lebenszeit einer lokalen Variable 
der Stack nicht wieder genutzt wird, liefert bei gcc der Schalter 
"-fstack-reuse". Historisch gewachsen halt...

Bisher hätte es bei mir nur in einem Programm Probleme gemacht, bei dem 
der Stack nicht groß war. Aber die Stacküberwachung hat gezeigt, dass es 
nie zu nicht wiederverwendeten Stackspeicher kam.

von Herbert (Gast)


Lesenswert?

Ich bin sehr positiv überrascht, wie sachlich diese Diskussion abläuft.

Wenn man bedenkt, wie sehr sich das Arduino System innerhalb der 8 Jahre 
etabliert hat, als dieser Post hier geschrieben wurde:

Beitrag "Re: Arduino - bringt's das ?"

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.