2023-01-09

VIRTUINO $ String

 


 Jak już chyba wspominałem za wymianę danych między aplikacją Virtuino a mikrocesorowym modułem odpowiada protokół komunikacji. W VIRTUINO 6 jest to biblioteka VirtuinoCM.h zaś w VIRTUINO IoT biblioteka  WebSocket. Jednak w obu przypadkach same dane przesyłane są w formacie String. Dziś o tym jak odczarować naszą daną z ciągu String  ... i odwrotnie. 



Dana typu String to naprawdę bardzo ciekawy typ. Niby niczym nie różni się w obsłudze do innych typów (int, long itd) ale nie do końca. Potrzeba do niej specjalnej biblioteki <string,h> by obsłużyć ten typ. Na szczęście w Arduino Ide jest on już wstępnie zaimplementowany. 

Dane typu String wyglądają podobnie do danych zadeklarowanych przez char. I tak

char tekst[] = "Jakiś tam tekst";

i

 String tekst = "Jakiś tam tekst";

dają identyczny wynik np. w procedurze 

 Serial.println(tekst);

 ale już próba zamiany  w funkcji z zadeklarowanym jednym typem danej na drugi typ wywoła bunt kompilatora.

Z nieznanych przyczyn wielu ortodoksów programowania brzydzi się stosowania zmiennej typu String.

Na szczęście nie musimy się tym przejmować tym bardziej że manipulowanie zmiennymi typu String jest niezwykle łatwe. Po pierwsze nie musimy przejmować się długością zmiennej. Posiada ona znacznik końca łańcucha (/0) i procedura obsługi takiej zmiennej wie jaka jest długość zmiennej bez wcześniejszej deklaracji jej długości. Ponadto przesyłanie wszelakich danych różnych typów jednym typem danych znakomicie upraszcza i uelastycznia operowanie danymi. Dlaczego? jeśli za pomocą danej typu String prześlemy "1" to po odebraniu takiego znaku możemy go dowolnie zinterpretować jako String, bit, baj int a nawet float. I nikt nam tego nie zabroni. A wszystko łatwo i przyjemnie wygląda dla oka ... chciałem powiedzieć dla naszego kodu.

Najłatwiej jest z konwersją czegokolwiek na String np.

int a = 1234;
String my_String = String(a);

W drugą stronę niestety nie ma tak prosto. Ale na szczęście tak naprawdę potrzebuję tylko dwóch typów konwersji - na liczbę stało lub zmiennoprzecinkową. W Arduino dostępne są dwie takie funkcje - dla int

String val = “1234”;
int result = val.toInt();  /

i float

String val = “1.2345”;
float result = val.toFloat();  /

istnieje jeszcze funkcja string.toDoble() jeśli potrzebujemy większej dokładności - liczba zamiast 4 zapisywana jest w 8 bajtach. To też liczba zmiennoprzecinkowa ale "sypie się " na dalszej pozycji

String val = “1.2345”;
double result = val.toDouble();  /

dla porównania liczba a = 1.123456789123456789

dla float wyświetla liczbę = 1.123456835746765358763354925031

zaś dla double = 1.123456789123457033596764631511
 
co jak widać float sypie się już na 7 miejscu po przecinku a double na 15

Te dwie konwersje wyczerpują 99% potrzeb konwersji danych w programie.  Nie musimy się przecież ograniczać pamięcią w ESP by stosować np. zmienne typy byte - załatwimy to typem int. 

Ale co zrobić jeśli mamy do przekonwertowania daną typu String na typ long - liczbę zawartą w 4 bajtach  w zakresie 2,147,483,648 to 2,147,483,647  i nie chcemy do tego użyć typu float czy double ?

Jeszcze nie wiem ale w przeciwieństwie do twardej elektroniki posiadającej sporo fizycznych ograniczeń w programowaniu jak w filmie możemy wyczarować wszystko na co przyjedzie nam ochota. Więc i ten problem gdy pojawi się w którymś z moich projektów pewnikiem zostanie rozwiązany przez ulubiony ciąg dalszy.

Suplement

Już wiem co zrobić gdy potrzebujemy zmiennej typu long, którą dostajemy w stringu. Przećwiczyłem to w procedurach wysyłania kodów transmisją 433MHz. Kod symulujący pilota RF musi być zawarty w zmiennej typu long a jeszcze lepiej unsigned long.

Teoretycznie powinna wystarczyć do tego funkcja atol(str.c_str())

Nie jest ona co prawda opisana w Arduino IDE jako dopuszczona do stosowania ale o dziwo działa. Działa dla ESP8266 ale nie wiem jak to będzie dla innych modułów. W każdym razie kompilator to łyka bez zahamowań. Niestety tak przetworzona dana typu String nie jest widziana poprawnie w procedurach transmisji RF biblioteki RCSwitch.h.  Czemu? nie wiem pewnie konwersja dodaje jakieś ukryte znaki do ciągu które w drukowaniu nie ujawniają się. 

Zastosowałem dodatkowy myk  pozwalający uzyskać prawidłową liczę   unsigned long akceptowalną przez bibliotekę transmisji 433MHz. 

unsigned long kodZapp = 0;

  kodZapp = atol(str.c_str());

      unsigned long a = kodZapp;

Liczba a ma już właściwy format akceptowany przez bibliotekę RCSwitch.h.

I to by było na tyle.



Brak komentarzy:

Prześlij komentarz