Um Daten über das Things-Netzwerk hin und her zu senden, müssen Sie Bytes verwenden. Diese Anleitung hilft Ihnen dabei, verschiedene Datentypen in so wenig Bytes wie möglich zu codieren.
Die beispiellose Reichweite der LoRaWAN-Technologie, auf der wir aufbauen, kostet geringe Bandbreite und begrenzte Sendezeit (die Anzahl der von Ihnen gesendeten Pakete). Glücklicherweise brauchen Sie kein Bild von diesem intelligenten Garagenbehälter, der geleert werden muss. Auch ein einzelnes bit
1
tun würde!,
Was ist ein byte?
Ein byte ist eine Gruppe von 8 bits. Ein Bit ist die grundlegendste Einheit und kann entweder 1 oder 0 sein. Ein Byte besteht nicht nur aus 8 Werten zwischen 0 und 1, sondern aus 256 (28) verschiedenen Kombinationen (eher Permutationen), die von 00000000
über z. B. 01010101
bis 11111111
reichen. Somit kann ein Byte eine Dezimalzahl zwischen 0(00) und 255 darstellen.
Verwirrt? Denken Sie daran, dass 3 Dezimalzahlen nicht nur für 3 Werte zwischen 0 und 9 stehen, sondern auch für 1000 (103) Permutationen von 0(00) bis 999.,
Erfahren Sie mehr darüber, wie Dinge funktionieren: Wie Bits und Bytes funktionieren und das Arduino Bit Math Tutorial, um mehr darüber zu erfahren.
Was ist ein Puffer von bytes?
Betrachten Sie Puffer als nur ein anderes Wort für ein Array, eine Liste, was auch immer mit Ihrer Programmiererfahrung in Resonanz steht. Wie ein Byte eine Gruppe von 8 Bits ist, ist ein Puffer eine Gruppe einer vordefinierten Anzahl von Bytes. Wenn wir eine Gruppe von 3 Bytes haben, könnte dies entweder 3 Werte zwischen 0 und 255 darstellen, aber auch einen einzelnen Wert zwischen 0 und 16777216 (2563).
Sehen Sie sich die Muster?, Die Anzahl der Auswahlmöglichkeiten pro Position (n) zur Potenz der Anzahl der Positionen (r) ist die Anzahl der Permutationen: nr. Erfahren Sie mehr über MathIsFun.com.
Was ist das Hex?
Oft wird eine Gruppe von Bytes angezeigt als:
FF F0 0F 11
War kein Byte eine Gruppe von 8 0
s und 1
s?, 🤔 Sie haben völlig Recht, aber genau wie wir bereits gesehen haben, dass 11111111
im guten alten Dezimalsystem 255 bedeutet, können wir es auch in FF im Hexadezimalsystem übersetzen, wo jede Position 16 (0-9 A-F) mögliche Werte hat. Der Vorteil ist, dass es kürzer und explizit über den Maximalwert ist (257 ist keine Option).,
Das obige Beispiel, das in das Dezimalsystem übersetzt und zur Lesbarkeit aufgefüllt wurde, lautet:
255 240 015 017
Um anzuzeigen, dass Sie 11
in hex und nicht zwei Bits oder der Zahl elf meinen, setzen Sie ihm den 0x
Formatierer voran. Um es zu sagen, meinen Sie binäre Verwendung B
.,h>Code
11
0x11
B11
An example for Arduino:
Yeah, I know… 0x
kind of blows the shorter-to-write advantage of hex., 🙃
Wie viele bytes kann ich senden?
Technisch gesehen können Sie 51 Bytes senden. Aber je mehr Bytes Sie senden, desto mehr Sendezeit kostet Sie das Paket und desto eher erreichen Sie Ihre maximal zugewiesene Zeit. Fragen Sie sich also nicht, wie viele Sie möglicherweise senden können, sondern fragen Sie, wie wenige den Job erledigen könnten.
Wie sende ich große Zahlen?
Eine bessere Frage wäre, wie Bereiche größer als 255 gesendet werden.
Index
Wenn die möglichen Werte, die Sie unterstützen müssten, nicht bei 0 beginnen und Sie den Mindestwert kennen, beginnen Sie mit der Indizierung dieser Zahl.,
Stellen Sie sich zum Beispiel vor, wir würden Werte zwischen 3400 und 3600 erwarten.,
Auf dem Gerät würden wir dies wie folgt codieren:
int myVal = 3450;const int myBase = 3400;byte payload = { myVal - myBase };
Und in den Anwendungsnutzlastfunktionen tun:
var myBase = 3400;decoded.myVal = bytes + myBase;
Umgekehrt hätten wir in der Nutzlastfunktion des Anwendungscodierers:
var myVal = 3450;var myBase = 3400;var bytes = ;
Und auf dem Gerät decodieren Sie dies mit:
int myBase = 3400;int myVal = payload + myBase;
Wie Sie sehen können, solange der Mindestwert bekannt ist und der Bereich unseres Wertes 256 oder weniger beträgt, können wir immer noch ein einzelnes Byte verwenden, ohne ins Schwitzen zu geraten., Überprüfen Sie unbedingt, ob Ihr Wert nicht größer als 3655 ist, um böse Fehler zu vermeiden.😅
Rund
Was ist nun, wenn der Bereich größer als 256 ist? Die nächste Frage wäre, ob Sie den genauen Wert kennen müssen. Wenn Ihr Sensor einen Bereich von 400 und eine Fehlermarge von 2 hat, verlieren Sie durch Runden des Werts keine Bedeutung. Sowohl 299 als auch 300 würden auf 150 runden, was in Ordnung ist.
Auf dem Gerät würden wir dies wie folgt codieren:
int myVal = 300;int errorMargin = 2byte payload = { round(myVal / errorMargin) };
Und in den Anwendungsnutzlastfunktionen tun:
var errorMargin = 2;decoded.myVal = bytes * errorMargin;
Sie werden die Idee für den anderen Weg bekommen.,
Benutze Wörter
Ein Wort ist 2 Bytes (außer auf Due, Zero und ähnlichen Boards, wo es 4 Bytes ist), was dir bereits einen riesigen Bereich von 65536 (2562) bringt. Der int-Datentyp ist ein Wort und Arduino wird mit und lowByte()
geliefert, um das linke und rechte Byte aus einem Wort zu extrahieren. Dies macht es wirklich einfach zu kodieren und zu dekodieren.
Encode (Arduino):
Decode (payload functions):
decoded.myVal = (bytes << 8) + bytes;
Sie fragen sich, worum es bei der
<<
geht?, Diese linke verschiebt die 8 Bits des ersten Bytes 8 Positionen nach links. Verwirrt? Überlegen Sie, wie wir die Zahl 11 als zwei 1 codieren und dekodieren können, indem wir die erste 1 um eine Position verschieben (10), bevor wir die andere hinzufügen. Wir werden als nächstes mehr über Bit Shifting sprechen.
Kodieren (nutzlast funktionen):
var myVal = 20000;var bytes = ;bytes = (myVal & 0xFF00) >> 8;bytes = (myVal & 0x00FF);
Nie gesehen
&
verwendet diese weise vor? Dies ist ein bitweises UND., Auf diese Weise fungiert die rechte Seite des Ausdrucks als Maske, um ein Byte auf Null zu setzen, sodass wir nur mit dem anderen Byte arbeiten können.
Decode (Arduino):
int myVal = ((int)(payload) << 8) + payload;
Shift-bits
Wenn der Bereich der erwarteten Werte ist größer als 65536, können wir den gleichen trick. Der einzige Unterschied besteht darin, dass wir Bits manuell verschieben müssen, wenn wir auf Arduino codieren, genau wie in der Nutzlastfunktion.
Angenommen, wir müssen ein long codieren, das 4 Bytes für einen Bereich von bis zu 4294967296 verwendet.,
Encode (Arduino):
Decode (payload Funktionen):
decoded.myVal = ((long)(bytes) << 24) + ((long)(bytes) << 16) + ((long)(bytes) << 8) + ((long)(bytes));
Wie zu senden negative zahlen?
Um den Unterschied zwischen -100 und 100 zu erkennen, benötigen Sie einen signierten Datentyp. Diese setzen das höchste (am weitesten links) Bit auf 1
, um anzuzeigen, dass es sich um eine negative Zahl handelt. Dies bedeutet, dass beispielsweise in einem Wort nur 15 der 16 Bits für die tatsächliche Zahl verfügbar sind, wodurch der Bereich von 65536 auf 32768 begrenzt wird.,
Index, round und shift
Die bisher verwendeten Datentypen sind alle signiert, was bedeutet, dass alle Tricks für negative Werte genauso gut funktionieren. Beachten Sie einfach den Maximalwert.
Vorzeichenlose Datentypen
Wenn Sie keine negativen Zahlen erwarten und einen größeren Bereich benötigen, verwenden Sie explizit unsigned int
oder unsigned long
.
Wie sende ich Dezimalzahlen?
Bisher haben wir uns nur mit gerundeten Zahlen beschäftigt. Was ist, wenn Sie mehr Präzision benötigen? Die Antwort ist sehr ähnlich wie wir große Zahlen indiziert oder gerundet haben., Einfach multiplizieren und teilen Sie den Wert, während Sie ihn kodieren und dekodieren.
Encode (Arduino):
Decode (payload funktionen):
decoded.myVal = bytes / 100;
Encode (payload funktionen):
bytes = Math.round(1.22 * 100);
Decode (Arduino):
float myVal = payload / 100.00;
Wie sende ich mehrere Nummern?
In vielen Fällen möchten Sie mehrere Werte in einer einzigen Nachricht senden. Beginnen Sie damit, jede einzelne Zahl in einen Byte-Puffer zu codieren und sie dann zu einem einzigen Puffer zu kombinieren.,
Kodieren (Arduino):
Sie fragen sich vielleicht, warum
memcpy()
payload + sizeOfPayloadA
akzeptiert, wie sie scheinen 🍏 und 🍊. Betrachten Sie es als eine Anweisung zum Kopieren in denpayload
– Puffer, aber nachdem der Punkt verschoben wurde, wird er mit der Länge der Payloads kopiert, die wir bisher hinzugefügt haben.,
Decode (payload Funktionen)
decoded.myValA = bytes.slice(0, 2);decoded.myValB = bytes.slice(2, 5);// Decode both byte arrays as we did before
Encode (payload Funktion)
// Encode both values as we did beforevar bytes = bytesA.concat(bytesB);
Decode (Arduino):
var payloadA;var payloadB;memcpy(payloadA,
Wie zu senden text?
Die kurze Antwort lautet: nicht. Text verwendet viele Bytes. Unicode definiert mehr als 128000 Zeichen, also würde das 3 Bytes pro Zeichen dauern! Es gibt selten gute Gründe, Text anstelle von Zahlen zu verwenden, abgesehen von der Übertragung einiger Benutzereingaben., Meistens genügen nur die alphanumerischen Zeichen, in diesem Fall können Sie mit ASCII-Zeichen davonkommen, die nur ein einziges Byte pro Zeichen verwenden. Jede Zeichenfolge muss mit einem NULL-Zeichen (0x00, ‚\0‘) beendet werden, um anzuzeigen, dass die Zeichenfolge beendet wurde.
Sie haben es nicht von mir gehört, aber so kodieren Sie eine Zeichenfolge:
, mit der Sie dekodieren würden:
decoded.myVal = String.fromCharCode.apply(null, bytes);