om gegevens heen en weer te sturen over het Things netwerk moet u bytes gebruiken. Deze gids zal u helpen bij het coderen van verschillende soorten gegevens in zo weinig bytes mogelijk.
het ongekende bereik van de LoRaWAN-technologie waarop we bouwen gaat ten koste van een lage bandbreedte en een beperkte zendtijd (het aantal keer de grootte van pakketten die u verzendt). Gelukkig, je hoeft niet een foto van die slimme garage bin die moet worden geleegd nodig. Zelfs een enkele bit
1
zou volstaan!,
Wat is een byte?
een byte is een groep van 8 bits. Een bit is de meest elementaire eenheid en kan 1 of 0 zijn. Een byte is niet alleen 8 waarden tussen 0 en 1, maar 256 (28) verschillende combinaties (in plaats van permutaties) variërend van 00000000
via bijvoorbeeld 01010101
tot 11111111
. Aldus, kan één byte een decimaal getal tussen 0(00) en 255 vertegenwoordigen.
verbaasd? Vergeet niet dat 3 decimale getallen ook niet alleen staan voor 3 waarden tussen 0 en 9, maar 1000 (103) permutaties van 0(00) tot 999.,
leer meer over hoe dingen werken: hoe Bits en Bytes werken en de Arduino Bit Math Tutorial om er meer over te leren.
Wat is een buffer van bytes?
denk aan buffer als gewoon een ander woord voor een array, lijst, wat resoneert met je programmeerervaring. Zoals een byte een groep van 8 bits is, is een buffer een groep van een vooraf gedefinieerd aantal bytes. Als we een groep van 3 bytes hebben, kan dit ofwel 3 waarden tussen 0 en 255 vertegenwoordigen, maar ook één enkele waarde tussen 0 en 16777216 (2563).
zie het patroon?, Het aantal keuzes per positie (n) tot de macht van het aantal posities (r) is het aantal permutaties: nr. MathIsFun.com.
wat de hex?
vaak ziet u een groep bytes weergegeven als:
FF F0 0F 11
was geen byte een groep van 8 0
s en 1
s?, 🤔 Je hebt helemaal gelijk, maar net zoals we al zagen 11111111
vertaalt naar 255 in het goede oude decimale systeem, kunnen we het ook vertalen naar FF in het hexadecimale systeem waar elke positie 16 (0-9 A-F) mogelijke waarden heeft. Het voordeel is dat het korter en expliciet is over de maximale waarde (257 is geen optie).,
het bovenstaande voorbeeld vertaald naar het decimale systeem en opgevuld voor leesbaarheid zou zijn:
255 240 015 017
om aan te geven dat u 11
In hex bedoelt en niet twee bits of het getal Elf, voegt u het voor met de0x
formatter. Om het te vertellen bedoel je binair gebruik B
.,h>Code
11
0x11
B11
An example for Arduino:
Yeah, I know… 0x
kind of blows the shorter-to-write advantage of hex., 🙃
hoeveel bytes kan ik verzenden?
technisch gezien kunt u 51 bytes versturen. Maar, hoe meer bytes u verzendt, hoe meer zendtijd het pakket u zal kosten en hoe eerder u uw maximaal toegewezen tijd zult raken. Dus, vraag jezelf niet af hoeveel je eventueel kunt sturen, maar vraag liever hoe weinig het werk zou kunnen doen.
hoe stuur ik grote getallen?
een betere vraag zou zijn hoe bereiken groter dan 255 te verzenden.
Index
als de mogelijke waarden die u zou moeten ondersteunen niet beginnen bij 0 en u weet de minimumwaarde, begin dan met indexeren op dat nummer.,
bijvoorbeeld, stel je voor dat we waarden tussen 3400 en 3600 verwachten.,
op het apparaat coderen we dit als:
int myVal = 3450;const int myBase = 3400;byte payload = { myVal - myBase };
en in de toepassing payload functies doen:
var myBase = 3400;decoded.myVal = bytes + myBase;
omgekeerd, in de toepassing encoder payload functie zouden we hebben:
var myVal = 3450;var myBase = 3400;var bytes = ;
en decodeer dit op het apparaat met:
int myBase = 3400;int myVal = payload + myBase;
zoals u kunt zien, zolang de minimumwaarde bekend is en het bereik van onze waarde 256 of minder is, kunnen we nog steeds een enkele byte gebruiken zonder te zweten., Controleer of uw waarde niet groter is dan 3655 om vervelende bugs te voorkomen.😅
rond
wat nu als het bereik groter is dan 256? De volgende vraag is of je de exacte waarde moet weten. Als uw sensor een bereik van 400 heeft en een foutmarge van 2, verliest u geen betekenis door de waarde af te ronden. Zowel 299 als 300 zou rond 150, dat is prima.
op het apparaat coderen we dit als:
int myVal = 300;int errorMargin = 2byte payload = { round(myVal / errorMargin) };
en in de toepassing payload functies doen:
var errorMargin = 2;decoded.myVal = bytes * errorMargin;
u krijgt het idee voor het omgekeerde.,
gebruik woorden
een woord is 2 bytes (behalve op Due, Zero en soortgelijke boards waar het 4 bytes is), wat je al een enorme range van 65536 (2562) geeft. Het INT-gegevenstype is een woord en Arduino wordt geleverd met highByte()
en lowByte()
om de linker en rechter byte uit een woord te extraheren. Dit maakt het heel gemakkelijk om te coderen en decoderen.
Encode (Arduino):
int myVal = 20000;byte payload;payload = highByte(myVal);payload = lowByte(myVal);
Decode (payload functies):
decoded.myVal = (bytes << 8) + bytes;
vraagt zich af wat de
<<
is ongeveer?, Deze links verschuift de 8 bits van de eerste byte 8 posities naar links. Verward? Denk na over hoe we het getal 11 kunnen coderen als twee 1 ‘ s en decoderen door de eerste 1 een positie omhoog te schuiven (waardoor het 10 wordt) voordat we de andere optellen. Daarna praten we verder over een beetje verschuiven.
coderen (payload functies):
var myVal = 20000;var bytes = ;bytes = (myVal & 0xFF00) >> 8;bytes = (myVal & 0x00FF);
nooit gezien
&
eerder op deze manier gebruikt? Dit is een beetje verstandig en., Op deze manier zal de rechterkant van de expressie fungeren als een masker om een byte uit te nul, zodat we met alleen de andere kunnen werken.
Decode (Arduino):
int myVal = ((int)(payload) << 8) + payload;
Shift bits
als het bereik van verwachte waarden groter is dan 65536 kunnen we dezelfde truc gebruiken. Het enige verschil is dat we handmatig bits moeten verschuiven wanneer we coderen op Arduino, net zoals we deden in de payload functie.
laten we zeggen dat we een long moeten coderen die 4 bytes gebruikt voor een bereik tot 4294967296.,
Encode (Arduino):
Decode (payload functies):
decoded.myVal = ((long)(bytes) << 24) + ((long)(bytes) << 16) + ((long)(bytes) << 8) + ((long)(bytes));
hoe stuur ik negatieve getallen?
om het verschil tussen -100 en 100 te zien heeft u een ondertekend gegevenstype nodig. Deze stellen het hoogste (meest linkse) bit in op 1
om aan te geven dat het een negatief getal is. Dit betekent dat bijvoorbeeld in een woord slechts 15 van de 16 bits beschikbaar zijn voor het werkelijke aantal, waardoor het bereik van 65536 tot 32768 wordt beperkt.,
Index, round en shift
De tot nu toe gebruikte gegevenstypen zijn allemaal ondertekend, wat betekent dat alle trucs net zo goed werken voor negatieve waarden. Wees je bewust van de maximale waarde.
unsigned data types
Als u geen negatieve getallen verwacht en een groter bereik nodig hebt, gebruik dan expliciet unsigned int
of unsigned long
.
hoe decimalen verzenden?
tot nu toe hebben we alleen afgeronde getallen behandeld. Wat als je meer precisie nodig hebt? Het antwoord lijkt erg op hoe we grote getallen hebben geïndexeerd of afgerond., Gewoon meerdere en verdeel de waarde als u coderen en decoderen.
Coderen (Arduino):
float myVal = 1.22;byte payload;payload = round(myVal * 100);
Decoderen (laadvermogen functies):
decoded.myVal = bytes / 100;
Coderen (laadvermogen functies):
bytes = Math.round(1.22 * 100);
Decoderen (Arduino):
float myVal = payload / 100.00;
het verzenden van meerdere nummers?
in veel gevallen wilt u meerdere waarden in één bericht verzenden. Begin met het coderen van elk individueel nummer naar een buffer van bytes en combineer ze vervolgens in een enkele buffer.,
Encode (Arduino):
u kunt zich afvragen waarom
memcpy()
payload + sizeOfPayloadA
accepteert zoals ze lijken 🍏 en 🍊. Zie het als een instructie om te kopiëren naar depayload
buffer, maar na het verplaatsen van het punt waarnaar het zal kopiëren, met de lengte van de payloads die we tot nu toe hebben toegevoegd.,
Decode (payload functies)
decoded.myValA = bytes.slice(0, 2);decoded.myValB = bytes.slice(2, 5);// Decode both byte arrays as we did before
Encode (payload functie)
// Encode both values as we did beforevar bytes = bytesA.concat(bytesB);
Decode (Arduino):
var payloadA;var payloadB;memcpy(payloadA,
hoe stuur ik tekst?
het korte antwoord is: niet doen. tekst gebruikt veel bytes. Unicode definieert meer dan 128000 karakters, dus dat zou 3 bytes per karakter nemen! Er zijn zelden goede redenen om tekst te gebruiken in plaats van nummers, afgezien van misschien het verzenden van een aantal gebruikersinvoer., Meestal volstaan alleen de alfanumerieke tekens, in dat geval kun je wegkomen met ASCII-tekens die slechts één byte per teken gebruiken. Elke tekenreeks moet worden beëindigd met een NULL (0x00, ‘\0’) teken om aan te geven dat de tekenreeks is beëindigd.
u hebt het niet van mij gehoord, maar zo codeert u een tekenreeks:
die u zou decoderen met:
decoded.myVal = String.fromCharCode.apply(null, bytes);