Per inviare dati avanti e indietro sulla Rete Things è necessario utilizzare bytes. Questa guida ti aiuterà a codificare diversi tipi di dati in meno byte possibili.
La gamma senza precedenti della tecnologia LoRaWAN che costruiamo su arriva al costo di bassa larghezza di banda e tempo di trasmissione limitato (il numero di volte la dimensione dei pacchetti inviati). Fortunatamente, non hai bisogno di una foto di quel bidone garage intelligente che ha bisogno di svuotato. Anche un singolo bit
1
farebbe!,
Che cos’è un byte?
Un byte è un gruppo di 8 bit. Un po ‘ è l’unità di base e può essere 1 o 0. Un byte non è solo 8 valori tra 0 e 1, ma 256 (28) combinazioni diverse (piuttosto permutazioni) che vanno da 00000000
via ad esempio 01010101
a 11111111
. Pertanto, un byte può rappresentare un numero decimale compreso tra 0 (00) e 255.
Perplesso? Ricorda che anche 3 numeri decimali non rappresentano solo 3 valori tra 0 e 9, ma 1000 (103) permutazioni da 0(00) a 999.,
Scopri di più su come funzionano le cose: come funzionano bit e byte e il tutorial di Arduino Bit Math per saperne di più.
Che cos’è un buffer di byte?
Pensa a buffer come solo un’altra parola per un array, un elenco, qualunque cosa risuoni con la tua esperienza di programmazione. Come un byte è un gruppo di 8 bit, un buffer è un gruppo di un numero predefinito di byte. Se abbiamo un gruppo di 3 byte, questo potrebbe rappresentare 3 valori tra 0 e 255, ma anche un singolo valore tra 0 e 16777216 (2563).
Vedere il modello?, Il numero di scelte per posizione (n) alla potenza del numero di posizioni (r) è il numero di permutazioni: nr. MathIsFun.com.
Che cosa l’esagono?
Spesso, vedrai un gruppo di byte visualizzato come:
FF F0 0F 11
non Era un byte di un gruppo di 8 0
e 1
s?, 🤔 Hai perfettamente ragione, ma proprio come abbiamo già visto 11111111
traduce in 255 nel buon vecchio sistema decimale, possiamo anche tradurlo in FF nel sistema esadecimale dove ogni posizione ha 16 (0-9 A-F) valori possibili. Il vantaggio è che è più breve ed esplicito sul valore massimo (257 non è un’opzione).,
L’esempio tradotto per il sistema decimale e imbottita per una maggiore leggibilità sarebbe:
255 240 015 017
Per indicare che si intende 11
in esadecimale e non due bit o il numero undici, prefisso con il 0x
formatter. Per dirlo intendi l’uso binario B
.,h>Code
11
0x11
B11
An example for Arduino:
Yeah, I know… 0x
kind of blows the shorter-to-write advantage of hex., How
Quanti byte posso inviare?
Tecnicamente, è possibile inviare 51 byte. Ma più byte invierai, più tempo di trasmissione il pacchetto ti costerà e prima raggiungerai il tempo massimo assegnato. Quindi, non chiedetevi quanti si può eventualmente inviare, ma piuttosto chiedere come pochi potrebbero fare il lavoro.
Come inviare grandi numeri?
Una domanda migliore sarebbe come inviare intervalli più grandi di 255.
Index
Se i possibili valori che dovresti supportare non iniziano da 0 e conosci il valore minimo, inizia indicizzando su quel numero.,
Ad esempio, immagina che ci aspetteremmo valori tra 3400 e 3600.,
il dispositivo avevamo codificare questo, come:
int myVal = 3450;const int myBase = 3400;byte payload = { myVal - myBase };
E nel payload dell’applicazione funzioni:
var myBase = 3400;decoded.myVal = bytes + myBase;
un altro modo, in applicazione encoder payload funzione si avrebbe:
var myVal = 3450;var myBase = 3400;var bytes = ;
E sul dispositivo di decodifica con:
int myBase = 3400;int myVal = payload + myBase;
Come si può vedere il tempo minimo per cui è noto il valore e la portata del nostro valore è di 256 o meno, si può ancora utilizzare un singolo byte senza rompere un sudore., Assicurati di controllare che il tuo valore non sia più grande di 3655 per evitare cattivi bug.Round
Round
Ora cosa succede se l’intervallo è maggiore di 256? La prossima domanda sarebbe se hai bisogno di conoscere il valore esatto. Se il sensore ha un intervallo di 400 e un margine di errore di 2, non si perderebbe alcun significato arrotondando il valore. Sia 299 che 300 arrotonderebbero a 150, il che va bene.
Sul dispositivo lo codifichiamo come:
int myVal = 300;int errorMargin = 2byte payload = { round(myVal / errorMargin) };
E nelle funzioni di payload dell’applicazione:
var errorMargin = 2;decoded.myVal = bytes * errorMargin;
Avrai l’idea per il contrario.,
Usa le parole
Una parola è di 2 byte (tranne su Due, Zero e schede simili dove è di 4 byte), che ti offre già una vasta gamma di 65536 (2562). Il tipo di dati int è una parola e Arduino viene fornito con highByte()
e lowByte()
per estrarre il byte sinistro e destro da una parola. Questo lo rende davvero facile da codificare e decodificare.
Codifica (Arduino):
int myVal = 20000;byte payload;payload = highByte(myVal);payload = lowByte(myVal);
Decode (payload funzioni):
decoded.myVal = (bytes << 8) + bytes;
vi chiedete a cosa
<<
è di circa?, Questa sinistra sposta gli 8 bit del primo byte 8 posizioni a sinistra. Confuso? Pensa a come potremmo codificare il numero 11 come due 1 e decodificare spostando il primo 1 in una posizione (rendendolo 10) prima di aggiungere l’altro. Parleremo più di bit shifting prossimo.
Codifica (funzioni di payload):
var myVal = 20000;var bytes = ;bytes = (myVal & 0xFF00) >> 8;bytes = (myVal & 0x00FF);
Mai visto
&
usato questo molto prima? Questo è un Bit per bit E., Usato in questo modo il lato destro dell’espressione fungerà da maschera per azzerare un byte in modo da poter lavorare solo con l’altro.
Decode (Arduino):
int myVal = ((int)(payload) << 8) + payload;
Shift bit
Se l’intervallo di valori attesi è maggiore di 65536 possiamo usare lo stesso trucco. L’unica differenza è che dobbiamo spostare manualmente i bit quando codifichiamo su Arduino, proprio come abbiamo fatto nella funzione payload.
Diciamo che abbiamo bisogno di codificare un long che utilizza 4 byte per un intervallo fino a 4294967296.,
Encode (Arduino):
Decode (payload functions):
decoded.myVal = ((long)(bytes) << 24) + ((long)(bytes) << 16) + ((long)(bytes) << 8) + ((long)(bytes));
Come inviare numeri negativi?
Per capire la differenza tra -100 e 100 è necessario un tipo di dati firmato. Questi impostano il bit più alto (più a sinistra) su 1
per indicare che è un numero negativo. Ciò significa che ad esempio in una parola sono disponibili solo 15 dei 16 bit per il numero effettivo, limitando l’intervallo da 65536 a 32768.,
Index, round and shift
I tipi di dati che abbiamo usato finora sono tutti firmati, il che significa che tutti i trucchi funzionano altrettanto bene per i valori negativi. Basta essere consapevoli del valore massimo.
Tipi di dati non firmati
Se non ti aspetti numeri negativi e hai bisogno di un intervallo più ampio, usa esplicitamenteunsigned int
ounsigned long
.
Come inviare decimali?
Finora abbiamo affrontato solo numeri arrotondati. Cosa succede se hai bisogno di più precisione? La risposta è molto simile a come abbiamo indicizzato o arrotondato grandi numeri., Semplicemente multiplo e dividi il valore mentre lo codifichi e lo decodifichi.
Codifica (Arduino):
float myVal = 1.22;byte payload;payload = round(myVal * 100);
Decode (payload funzioni):
decoded.myVal = bytes / 100;
Codifica (payload funzioni):
bytes = Math.round(1.22 * 100);
Decode (Arduino):
float myVal = payload / 100.00;
Come inviare più numeri?
In molti casi ti consigliamo di inviare più valori in un singolo messaggio. Iniziare codificando ogni singolo numero in un buffer di byte e quindi combinarli in un singolo buffer.,
Encode (Arduino):
Potresti chiederti perché
memcpy()
accettapayload + sizeOfPayloadA
come sembrano and e 🍊. Pensalo come un’istruzione per copiare nel bufferpayload
, ma dopo aver spostato il punto copierà, con la lunghezza dei payload che abbiamo aggiunto finora.,
Decode (payload funzioni)
decoded.myValA = bytes.slice(0, 2);decoded.myValB = bytes.slice(2, 5);// Decode both byte arrays as we did before
Codifica (payload funzione)
// Encode both values as we did beforevar bytes = bytesA.concat(bytesB);
Decode (Arduino):
var payloadA;var payloadB;memcpy(payloadA,
Come inviare un messaggio di testo?
La risposta breve è: non farlo. Il testo utilizza molti byte. Unicode definisce più di 128000 caratteri, in modo che richiederebbe 3 byte per carattere! Raramente ci sono buone ragioni per usare il testo invece dei numeri, a parte forse la trasmissione di alcuni input dell’utente., La maggior parte delle volte bastano solo i caratteri alfanumerici, in tal caso puoi scappare usando caratteri ASCII che usano solo un singolo byte per carattere. Ogni stringa deve essere terminata con un carattere NULL (0x00, ‘\0′) per indicare che la stringa è terminata.
Non l’hai sentito da me, ma ecco come codificheresti una stringa:
Che decodificheresti con:
decoded.myVal = String.fromCharCode.apply(null, bytes);