för att skicka data fram och tillbaka över Things Network måste du använda byte. Den här guiden hjälper dig att koda olika typer av data i så små byte som möjligt.
det oöverträffade utbudet av LoRaWAN-tekniken som vi bygger på kommer till kostnaden för låg bandbredd och begränsad lufttid (antalet gånger storleken på paket du skickar). Lyckligtvis, du behöver inte en bild av den smarta garage bin som behöver tömmas. Även en enda bit
1
skulle göra!,
Vad är en byte?
en byte är en grupp på 8 bitar. Lite är den mest grundläggande enheten och kan vara antingen 1 eller 0. En byte är inte bara 8 värden mellan 0 och 1, utan 256 (28) olika kombinationer (snarare permutationer) som sträcker sig från 00000000
via t.ex. 01010101
till 11111111
. Således kan en byte representera ett decimaltal mellan 0 (00) och 255.
förbryllad? Kom ihåg att 3 decimaler inte bara står för 3 värden mellan 0 och 9, Men 1000(103) permutationer från 0 (00) till 999.,
Läs mer om hur saker fungerar: hur bitar och byte fungerar och Arduino Bit Math Tutorial för att lära dig mer om det.
Vad är en buffert av byte?
Tänk på buffert som bara ett annat ord för en array, lista, oavsett resonerar med din programmeringsupplevelse. Som en byte är en grupp av 8 bitar, en buffert är en grupp av ett fördefinierat antal byte. Om vi har en grupp på 3 byte kan detta antingen representera 3 värden mellan 0 och 255, men också ett enda värde mellan 0 och 16777216 (2563).
se mönstret?, Antalet val per position (n) till kraften i antalet positioner (r) är antalet permutationer: nr. Läs mer om MathIsFun.com.
vad hex?
ofta visas en grupp byte som:
FF F0 0F 11
var inte en byte en grupp på 80
s och1
s?, 🤔 Du är helt rätt, men precis som vi såg redan 11111111
översätter till 255 i den gamla goda decimal system, kan vi också översätta det till FF i det hexadecimala systemet där varje position har 16 (0-9 A-F) möjliga värden. Fördelen är att den är kortare och explicit om det maximala värdet (257 är inte ett alternativ).,
ovanstående exempel översatt till decimalsystemet och vadderat för läsbarhet skulle vara:
255 240 015 017
för att indikera att du menar 11
I hex och inte två bitar eller nummer elva, prefixar du det med 0x
formatter. För att berätta det menar du binär användning B
.,h>Code
11
0x11
B11
An example for Arduino:
Yeah, I know… 0x
kind of blows the shorter-to-write advantage of hex.,
hur många byte kan jag skicka?
Tekniskt kan du skicka 51 byte. Men ju fler Byte du skickar desto mer tid kommer paketet att kosta dig och ju tidigare du kommer att träffa din maximala tilldelade tid. Så fråga dig inte hur många du kan skicka utan fråga hur få som kan göra jobbet.
Hur skickar man stora nummer?
en bättre fråga skulle vara hur man skickar intervall större än 255.
Index
om de möjliga värden du behöver för att stödja inte startar vid 0 och du vet minimivärdet, börja med att indexera på det numret.,
Tänk dig till exempel att vi förväntar oss värden mellan 3400 och 3600.,
på enheten skulle vi koda detta som:
int myVal = 3450;const int myBase = 3400;byte payload = { myVal - myBase };
och i programmet nyttolastfunktioner gör:
var myBase = 3400;decoded.myVal = bytes + myBase;
tvärtom, i programmet kodare nyttolastfunktion vi skulle ha:
var myVal = 3450;var myBase = 3400;var bytes = ;
int myVal = 3450;const int myBase = 3400;byte payload = { myVal - myBase };
och på enheten avkoda detta med:
int myBase = 3400;int myVal = payload + myBase;
som du kan se så länge minimivärdet är känt och intervallet av vårt värde är 256 eller mindre, kan vi fortfarande använda en enda byte utan att bryta en svett., Var noga med att kontrollera ditt värde är inte större än 3655 för att förhindra otäcka buggar.vad händer om intervallet är större än 256? Nästa fråga skulle vara om du behöver veta det exakta värdet. Om din sensor har en räckvidd på 400 och en felmarginal på 2, skulle du inte förlora någon mening genom att avrunda värdet. Både 299 och 300 skulle runda till 150, vilket är bra.
på enheten skulle vi koda detta som:
int myVal = 300;int errorMargin = 2byte payload = { round(myVal / errorMargin) };
och i applikations nyttolastfunktionerna gör:
var errorMargin = 2;decoded.myVal = bytes * errorMargin;
du får idén för den andra vägen runt.,
använd ord
ett ord är 2 byte (förutom på grund, noll och liknande brädor där det är 4 byte), som redan får dig ett stort utbud av 65536 (2562). Int datatypen är ett ord och Arduino levereras med highByte()
och lowByte()
för att extrahera vänster och höger byte från ett ord. Detta gör det verkligen lätt att koda och avkoda.
koda (Arduino):
int myVal = 20000;byte payload;payload = highByte(myVal);payload = lowByte(myVal);
avkoda (nyttolastfunktioner):
decoded.myVal = (bytes << 8) + bytes;
undrar vad
<<
handlar om?, Detta vänster skiftar 8 bitar av den första byte 8 positioner till vänster. Förvirrad? Tänk på hur vi kan koda nummer 11 som två 1 och avkoda genom att flytta den första 1 upp en position (vilket gör det 10) innan du lägger till den andra. Vi pratar mer om lite skiftande nästa.
koda (nyttolastfunktioner):
var myVal = 20000;var bytes = ;bytes = (myVal & 0xFF00) >> 8;bytes = (myVal & 0x00FF);
aldrig sett
&
använde detta sätt tidigare? Detta är en Bitvis OCH., Används på detta sätt kommer den högra sidan av uttrycket att fungera som en mask för att nollställa en byte så att vi kan arbeta med bara den andra.
avkoda (Arduino):
int myVal = ((int)(payload) << 8) + payload;
Skift bitar
om intervallet av förväntade värden är större än 65536 kan vi använda samma trick. Den enda skillnaden är att vi måste manuellt byta bitar när vi kodar på Arduino, precis som vi gjorde i nyttolastfunktionen.
låt oss säga att vi måste koda en lång som använder 4 byte för ett intervall upp till 4294967296.,
koda (Arduino):
avkoda (nyttolastfunktioner):
decoded.myVal = ((long)(bytes) << 24) + ((long)(bytes) << 16) + ((long)(bytes) << 8) + ((long)(bytes));
Hur skickar du negativa tal?
för att skilja mellan -100 och 100 behöver du en signerad datatyp. Dessa anger den högsta (vänster-mest) biten till 1
för att indikera att det är ett negativt tal. Detta innebär att till exempel i ett ord endast 15 av de 16 bitarna är tillgängliga för det faktiska numret, vilket begränsar intervallet från 65536 till 32768.,
Index, round and shift
de datatyper vi använt hittills är alla signerade, vilket innebär att alla tricks fungerar lika bra för negativa värden. Var bara medveten om det maximala värdet.
osignerade datatyper
om du inte förväntar dig negativa tal och behöver ett större intervall, använd uttryckligenunsigned int
ellerunsigned long
.
Hur skickar man decimaler?
hittills har vi bara behandlat avrundade tal. Vad händer om du behöver mer precision? Svaret mycket lik hur vi indexerade eller rundade stora tal., Helt enkelt flera och dela upp värdet när du kodar och avkodar det.
koda (Arduino):
float myVal = 1.22;byte payload;payload = round(myVal * 100);
avkoda (nyttolastfunktioner):
decoded.myVal = bytes / 100;
koda (nyttolastfunktioner):
bytes = Math.round(1.22 * 100);
decode (Arduino):
float myVal = payload / 100.00;
Hur skickar du flera nummer?
i många fall vill du skicka flera värden i ett enda meddelande. Börja med att koda varje enskilt nummer till en buffert av byte och sedan kombinera dem till en enda buffert.,
koda (Arduino):
Du kanske undrar varför
memcpy()
accepterarpayload + sizeOfPayloadA
som de verkar vara ute efter och. Tänk på det som en instruktion att kopiera tillpayload
bufferten, men efter att ha flyttat punkten kommer den att kopiera till, med längden på de nyttolaster vi lagt till hittills.,
avkoda (nyttolastfunktioner)
decoded.myValA = bytes.slice(0, 2);decoded.myValB = bytes.slice(2, 5);// Decode both byte arrays as we did before
koda (nyttolastfunktion)
// Encode both values as we did beforevar bytes = bytesA.concat(bytesB);
avkoda (Arduino):
var payloadA;var payloadB;memcpy(payloadA,
Hur skickar man text?
det korta svaret är: gör det inte. Text använder många byte. Unicode definierar mer än 128000 tecken, så det skulle ta 3 byte per tecken! Det finns sällan goda skäl att använda text i stället för siffror, förutom att kanske överföra några användarinmatningar., För det mesta räcker bara de alfa-numeriska tecknen, i så fall kan du komma undan genom att använda ASCII-tecken som bara använder en enda byte per tecken. Varje sträng måste avslutas med ett NULL-tecken (0x00, \0) för att ange att strängen har avslutats.
Du hörde det inte från mig, men så här kodade du en sträng:
som du skulle avkoda med:
decoded.myVal = String.fromCharCode.apply(null, bytes);