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?
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.
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
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.
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.
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".
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.
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.
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.
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? ;-)
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.
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
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.
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....
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.
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.
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.
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.
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...)
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.
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.
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 ;-)
>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.
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
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.
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.
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.
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"
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.
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.
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.
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 ?"