aby wysyłać dane tam i z powrotem przez the Things Network musisz użyć bajtów. Ten przewodnik pomoże Ci kodować różne typy danych w jak najmniejszych bajtach.
bezprecedensowy zakres technologii LoRaWAN, na którym budujemy, odbywa się kosztem niskiej przepustowości i ograniczonego czasu antenowego (liczba razy wielkości przesyłanych paczek). Na szczęście nie potrzebujesz zdjęcia tego inteligentnego kosza garażowego, który trzeba opróżnić. Wystarczy nawet jeden bit
1
!,
Co to jest bajt?
bajt jest grupą 8 bitów. Bit jest najbardziej podstawową jednostką i może wynosić 1 lub 0. Bajt to nie tylko 8 wartości pomiędzy 0 a 1, ale 256 (28) różnych kombinacji (raczej permutacji) od 00000000
poprzez np. 01010101
do 11111111
. Tak więc jeden bajt może reprezentować liczbę dziesiętną od 0 (00) do 255.
Pamiętaj, że 3 liczby dziesiętne nie oznaczają tylko 3 wartości od 0 do 9, ale 1000(103) permutacji od 0 (00) do 999.,
Dowiedz się więcej o tym, jak działa: jak działają bity i bajty oraz Tutorial Arduino bit Math, aby dowiedzieć się więcej na ten temat.
Co to jest bufor bajtów?
pomyśl o buforze jako o innym słowie na tablicę, listę, cokolwiek współgra z twoim doświadczeniem programistycznym. Podobnie jak bajt jest grupą 8 bitów, bufor jest grupą predefiniowanej liczby bajtów. Jeśli mamy grupę 3 bajtów, może to reprezentować 3 wartości między 0 a 255, ale także jedną pojedynczą wartość między 0 a 16777216 (2563).
Zobacz wzór?, Liczba wyborów na pozycję (n) do potęgi liczby pozycji (r) jest liczbą permutacji: nr. Dowiedz się więcej na MathIsFun.com.
What the hex?
często zobaczysz grupę bajtów wyświetlaną jako:
FF F0 0F 11
czy bajt nie był grupą 80
s I1
s?, 🤔 Masz całkowitą rację, ale tak jak już widzieliśmy11111111
przekłada się na 255 W starym, dobrym systemie dziesiętnym, możemy również przetłumaczyć go na FF w systemie szesnastkowym, gdzie każda pozycja ma 16 (0-9 A-F) możliwych wartości. Zaletą jest to, że jest krótszy i wyraźny o maksymalnej wartości (257 nie jest opcją).,
powyższy przykład przetłumaczony na system dziesiętny i wyściełany pod kątem czytelności byłby następujący:
255 240 015 017
aby wskazać, że masz na myśli 11
w szesnastkach, a nie dwóch bitach lub jedenastu, należy przedrostek 0x
formatter. Aby to powiedzieć, masz na myśli użycie binarne B
.,h>Code
11
0x11
B11
An example for Arduino:
Yeah, I know… 0x
kind of blows the shorter-to-write advantage of hex., 🙃
ile bajtów mogę wysłać?
technicznie można wysłać 51 bajtów. Ale im więcej bajtów wyślesz, tym więcej czasu antenowego będzie cię kosztować paczka i tym szybciej osiągniesz swój maksymalny wyznaczony czas. Więc nie pytaj siebie, ile możesz wysłać, ale raczej zapytaj, jak niewielu może wykonać tę pracę.
jak wysyłać duże liczby?
lepszym pytaniem byłoby jak wysyłać zakresy większe niż 255.
Index
Jeśli Możliwe wartości, które musisz obsługiwać, nie zaczynają się od 0 i znasz minimalną wartość, zacznij od indeksowania na tej liczbie.,
na przykład wyobraźmy sobie, że spodziewamy się wartości między 3400 a 3600.,
na urządzeniu kodujemy to jako:
int myVal = 3450;const int myBase = 3400;byte payload = { myVal - myBase };
a w funkcji payload aplikacji robimy:
var myBase = 3400;decoded.myVal = bytes + myBase;
odwrotnie, w funkcji payload encodera aplikacji mamy:
var myVal = 3450;var myBase = 3400;var bytes = ;
i na urządzeniu zdekoduj to za pomocą:
int myBase = 3400;int myVal = payload + myBase;
jak widać tak długo, jak znana jest minimalna wartość i zakres naszej wartości wynosi 256 lub mniej, możemy nadal używać pojedynczego bajtu bez najmniejszego potu., Upewnij się, że twoja wartość nie jest większa niż 3655, aby zapobiec paskudnym błędom.😅
okrągłe
a co jeśli zakres jest większy niż 256? Następne pytanie brzmi, czy musisz znać dokładną wartość. Jeśli twój czujnik ma zakres 400 i margines błędu 2, nie stracisz żadnego znaczenia zaokrąglając wartość. Zarówno 299, jak i 300 zaokrąglą się do 150, co jest w porządku.
na urządzeniu kodujemy to jako:
int myVal = 300;int errorMargin = 2byte payload = { round(myVal / errorMargin) };
a w aplikacji payload functions do:
var errorMargin = 2;decoded.myVal = bytes * errorMargin;
pojawi się pomysł na odwrotnie.,
użyj słów
słowo ma 2 bajty (z wyjątkiem Due, Zero i podobnych tablic, gdzie jest 4 bajty), co daje już ogromny zakres 65536 (2562). Typ danych int to słowo, a Arduino zawiera highByte()
IlowByte()
, aby wyodrębnić lewy i prawy bajt ze słowa. Dzięki temu kodowanie i dekodowanie jest naprawdę łatwe.
kodowanie (Arduino):
int myVal = 20000;byte payload;payload = highByte(myVal);payload = lowByte(myVal);
dekodowanie (funkcje ładunku):
decoded.myVal = (bytes << 8) + bytes;
<<
jest o?, Ten Lewy przesuwa 8 bitów pierwszego bajtu 8 pozycji w lewo. Zdezorientowany? Zastanów się, jak możemy zakodować liczbę 11 jako dwa jedynki i dekodować, przesuwając pierwszą jedynkę w górę o jedną pozycję (czyniąc ją 10) przed dodaniem drugiej. Porozmawiamy później o przesunięciu bitów.
kodowanie (funkcje ładunku):
var myVal = 20000;var bytes = ;bytes = (myVal & 0xFF00) >> 8;bytes = (myVal & 0x00FF);
nigdy nie widziałem
&
używałem tego dużo wcześniej? To jest trochę i., W ten sposób prawa strona wyrażenia będzie działać jako maska, aby zerować jeden bajt, abyśmy mogli pracować tylko z drugim.
Decode (Arduino):
int myVal = ((int)(payload) << 8) + payload;
Shift bits
Jeśli zakres oczekiwanych wartości jest większy niż 65536 możemy użyć tej samej sztuczki. Jedyną różnicą jest to, że musimy ręcznie przesuwać bity podczas kodowania na Arduino, tak jak zrobiliśmy w funkcji ładunku.
Załóżmy, że musimy zakodować long, który używa 4 bajtów dla zakresu do 4294967296.,
kodowanie (Arduino):
dekodowanie (funkcje ładunku):
decoded.myVal = ((long)(bytes) << 24) + ((long)(bytes) << 16) + ((long)(bytes) << 8) + ((long)(bytes));
jak wysłać liczby ujemne?
aby odróżnić -100 od 100, potrzebny będzie podpisany typ danych. Ustawiają one najwyższy (lewy-najwyższy) bit na 1
, aby wskazać, że jest to liczba ujemna. Oznacza to, że na przykład w słowie tylko 15 z 16 bitów jest dostępnych dla rzeczywistej liczby, ograniczając zakres od 65536 do 32768.,
Index, round I shift
używane do tej pory typy danych są podpisane, co oznacza, że wszystkie sztuczki działają równie dobrze dla wartości ujemnych. Po prostu należy pamiętać o maksymalnej wartości.
niepodpisane typy danych
Jeśli nie oczekujesz liczb ujemnych i potrzebujesz większego zakresu, użyj jawnieunsigned int
lubunsigned long
.
Jak wysłać cyfry?
do tej pory zajmowaliśmy się tylko zaokrąglonymi liczbami. A jeśli potrzebujesz większej precyzji? Odpowiedź bardzo podobna do tego, jak indeksowaliśmy lub zaokrąglaliśmy duże liczby., Wystarczy wiele i podzielić wartość podczas kodowania i dekodowania.
kodowanie (Arduino):
float myVal = 1.22;byte payload;payload = round(myVal * 100);
dekodowanie (funkcje ładunku):
decoded.myVal = bytes / 100;
kodowanie (funkcje ładunku):
bytes = Math.round(1.22 * 100);
decode (Arduino):
float myVal = payload / 100.00;
jak wysłać wiele numerów?
w wielu przypadkach będziesz chciał wysłać wiele wartości w jednej wiadomości. Zacznij od zakodowania każdej pojedynczej liczby do bufora bajtów, a następnie połącz je w jeden bufor.,
Koduj (Arduino):
możesz się zastanawiać, dlaczego
memcpy()
akceptujepayload + sizeOfPayloadA
jak się wydają 🍏 i 🍊. Pomyśl o tym jak o instrukcji kopiowania do buforapayload
, ale po przeniesieniu punktu skopiuje się do niego, z długością dodanych do tej pory ładunków.,
dekodowanie (funkcje ładunku)
decoded.myValA = bytes.slice(0, 2);decoded.myValB = bytes.slice(2, 5);// Decode both byte arrays as we did before
dekodowanie (funkcja ładunku)
// Encode both values as we did beforevar bytes = bytesA.concat(bytesB);
dekodowanie (Arduino):
var payloadA;var payloadB;memcpy(payloadA,
jak wysłać SMS?
krótka odpowiedź brzmi: nie. tekst używa dużo bajtów. Unicode definiuje więcej niż 128000 znaków, więc zajmuje to 3 bajty na znak! Rzadko istnieją dobre powody, aby używać tekstu zamiast liczb, poza przekazaniem niektórych danych wejściowych użytkownika., W większości przypadków wystarczą tylko znaki alfanumeryczne, w takim przypadku można uciec za pomocą znaków ASCII, które używają tylko jednego bajtu na znak. Każdy łańcuch musi być zakończony znakiem NULL (0x00,' \0′), aby wskazać koniec łańcucha.
nie słyszałeś tego ode mnie, ale oto jak zakodowałeś ciąg znaków:
którym dekodowałeś:
decoded.myVal = String.fromCharCode.apply(null, bytes);