APPS

Z David Seidl
Verze z 24. 4. 2020, 19:35, kterou vytvořil Sei01 (diskuse | příspěvky) (→‎Práce s knihovnou OpenCV)
(rozdíl) ← Starší verze | zobrazit aktuální verzi (rozdíl) | Novější verze → (rozdíl)
Skočit na navigaci Skočit na vyhledávání

Úvod k mikropočítačům

Datová typy

V programech můžete používat následující datový typy.

  • signed char −128 ⋯ 127
  • signed short, signed int −32768 ⋯ 32767
  • signed long −2147483648 ⋯ 2147483647
  • signed long long −9223372036854775808 ⋯ 9223372036854775807


  • unsigned char 0 ⋯ 255
  • unsigned short, unsigned int 0 ⋯ 65535
  • unsigned long 0 ⋯ 4294967295
  • unsigned long long 0 ⋯ 18446744073709551615


Neuvedete-li u datového typu zdali je znaménkový či neznaménkový bere se standardně jako znaménkový.

Zápis čísel

Je možné použít následující zápisy čísel

Dekadický

int i   =  10578;
char ch = -10;
float f =  13.54;

Hexadecimální

int i   = 0x12B7;
char ch = 0xF1;

Bitový

int i   = 0b1101001010010110;
char ch = 0b10001101;

Uvědomte si že 0xA = 10 = 0b1010. Jedná se o zápis jednoho čísla v různých číselných soustavách.

Aritmetické, logické a bitové operátory jazyka C

  • Aritmetické +, -, *, /, %

První čtyři operátory viz základní škola. Operátor modulo % vrací zbytek po celočíselném dělení. Tedy 11 % 2 = 1, 11 % 5 = 1, 11 % 11 = 0

Zkrácený zápis aritmetických operátorů v jazyce C

x++, ++x     x = x + 1
x--, --x     x = x - 1
x += y       x = x + y
x -= y       x = x - y
x *= y       x = x * y
x /= y       x = x / y
x %= y       x = x % y
  • Logické &&, ||, !
Logický součin                Logický součet                 Logická negace
   lež && lež    => lež          lež || lež    => lež        !lež    => pravda
   lež && pravda => lež          lež || pravda => pravda     !pravda => lež
pravda && lež    => lež       pravda || lež    => pravda
pravda && pravda => pravda    pravda || pravda => pravda

Kde pravda je číslo nenulové a lež je číslo nula.

  • Bitové &, |, ~, ^, <<, >>
Bitový součin    Bitový součet     Bitový exclusive or     Bitová negace
0 & 0 => 0       0 | 0 => 0        0 ^ 0 => 0              ~1 => 0
0 & 1 => 0       0 | 1 => 1        0 ^ 1 => 1              ~0 => 1
1 & 0 => 0       1 | 0 => 1        1 ^ 0 => 1
1 & 1 => 1       1 | 1 => 1        1 ^ 1 => 0
Příklad: 5 & 3 = 1 protože 0b101 & 0b011 = 0b001
Příklad: 5 | 3 = 7 protože 0b101 | 0b011 = 0b111
Příklad: 5 ^ 3 = 6 protože 0b101 ^ 0b011 = 0b110
Příklad: ~5 =  protože ~0b101 = 0b11111010, pokud je 5 osmi bitové číslo
Bitový posun
0b01 << 1 => 0b10
0b10 >> 1 => 0b01
Příklad: 5 << 3 = 40 protože 0b101 << 3 = 0b101000
Příklad: 5 >> 3 = 0  protože 0b101 >> 3 = 0b000000

Zkrácený zápis logických operátorů v jazyce C

x >>= y   x = x >> y
x <<= y   x = x << y
x &= y    x = x & y
x |= y    x = x | y
x ^= y    x = x ^ y


Často dochází k záměně logických a bitových operátorů log. součtu a součinu
Příklad časté zámeny:

char x = 5;
char y = 2;

if(x && y) {...} //PRAVDA

if(x & y)  {...} //LEŽ


Komunikace s periferiemi pomocí AT příkazů

Mezi nejčastější komunikační protokoly, které se využívají při sériové asynchornní komunikaci jsou takzvané AT příkazy. Jednotlivé implementace AT příkazů se můžou mírně lišit, nicméně je zaveden standard, který se obecně dodržuje.

Komunikace nadřazeného zařízení s periférií pomocí AT příkazů probíhá stylem dozat odpověď. Předpokládejme že parametry sériové komunikace mezi nadřazeným zařízením a serverem jsou nastaveny schodně. V tomto stavu může procesor jako nadřazeného zařízení zaslat definovaný textový řetězec po sériové lince. Tento řetězec je ukončen netisknutelnými znaky "\r\n". Poté co zařízení odchytí sekvenci těchto dvou znaků, začne vyhodnocovat výraz, který byl uveden před nimi. Seznam podporovaných výrazů při komunikaci AT příkazy je k dispozici v dokumentaci každého zařízení. Nicméně některé AT příkazy se staly standardem.

Jedním ze standardizovaných AT příkazů je prostý výraz "AT". Po zaslání tohoto výrazu musí zařízení odpovědět řetězcem "OK\n\r". Čímž zařízení definuje, že je připraveno ke komunikaci.

Konvence komunikace AT příkazy pro modul RHF76-052

# příkazy jsou "case sensitive"
# na každý příkaz následuje odpověď
# příkaz nesmí být delší než 582 znaků
# validní příkaz musí končit '\n' nebo také '\r\n'
# pokud je zapnutá funkce: "command time out" není nutné ukončení '\n'
# defaultní nastavení komunikace na sériovém portu je: 8bitů, bez parity, jeden stop bit

Použité symboly

# =      --> nastavení hodnoty příkazu
# ?      --> dotaz
# :      --> vylistování vstupních parametrů
# +      --> prefix před příkazem
# ,      --> oddělovač parametrů
# mezera --> může být použita pro formátování příkazu

Pro získání informace o aktuálním stavu daného příkazu je možné zadat příkaz v následujících formátech:

AT+COMMAND
AT+COMMAND?
AT+COMMAND=?

Zápis dat se provádí následovně:

AT+COMMAND=DATA

Odpověď na dotaz je formátována následujícím způsobem:

+COMMAND:“RETURNDATA”

Možné chybové návratové kody:

-1 Počet parametrů je neplatný
-2 Obsah parametru je neplatný
-3 Funkce API vrací chybu při předání uživatelského parametru
-4 LoRaWAN modem nemůže uložit parametr do EEPROM
-5 Příkaz je v současné době zakázán
-6 Vyskytne se neznámá chyba
-7 Neexistuje dostatek prostředků k provedení operace uživatele
-10 Příkaz neznámý
-11 Příkaz má nesprávný formát
-12 Příkaz není dostupný v aktuálním režimu ("AT + MODE")
-20 Příliš mnoho parametrů. LoRaWAN modem podporuje max. 15 parametrů
-21 Délka příkazu je příliš dlouhá (přes 528bytes)
-22 Příkaz nebyl zakončen v časovém limitu, příkaz musí skončit s <LF>
-23 Byl přijat neplatný znak

Jednoduchý program pro komunikaci s LoraWAN modemem prostřednitvím terminálu v PC

#include "mbed.h" 
 
Serial pc(USBTX, USBRX);
 
Serial lora_uart(PTC4, PTC3);
DigitalOut lora_reset(PTA1);
 
int main() {
   pc.baud(115200);
   pc.printf("Hello World from FRDM-K64F board.\n");

   lora_reset = 0;
   wait_ms(100);
   lora_reset = 1;
   wait_ms(100);

   lora_uart.baud(9600);

   while (true) {
   	if(lora_uart.readable())
   		pc.putc(lora_uart.getc());

      	if(pc.readable())
       	lora_uart.putc(pc.getc());
   }
}

Po spuštění výše uvedeného programu, můžete v terminálovém programu na PC zaslat příkaz AT. měli by jste obdržet následující odpověď:

+AT: OK


Komunitní síť The Things Network

https://www.thethingsnetwork.org/

Jedná se o komunitní síť která je založená na protokolu LoraWAN. V rámci celého světa je možné nalézt mnoho přístupových bodů pro tuto síť. V porubském areálu VŠB se vyskytuje několik těchto přístupových bodů. Proto, aby jste byly schopni připojit vlastní zařízení je nejdříve nutné se zaregistrovat do této sítě.

Na hlavní stránce The Things Network klikněte na "SIGN UP". Zadejte potřebné údaje a zaregistrujte se v síti TNN.

V záložce "CONZOLE" klikněte na "APPLICATIONS". V pravé části klikněte na odkaz "add application". V položce "Application ID" zadejte "apps". V položce "Handler registration" zanechte hodnotu "tnn-handler-eu". Dokončete registraci aplikace.

Nyní v aplikaci "apps" zadejte "register device". V položce "Device ID" zařízení vhodně pojmenujte. V terminálu který komunikuje s obvodem RHF76-052 zadejte AT příkaz "AT+ID" a do položky "Device EUI" zadejte osm hexadecimálních číslic. Dokončete registraci zařízení.

Při registraci zařízení byl vygenerován "Application EUI" a "App Key". Tyto klíče nastavte v obvodu RHF76-052 pomocí AT příkazů:

AT+ID=APPEUI,123456789ABCDEFF
AT+ID=DEVEUI,123456789ABCDEFF

Pomocí AT příkazu KEY zadejte vygenerovaný APPKey.

AT+KEY=APPKEY,BE11C1299055A251616EACFFFFFFFFFF

Nastavte mod OTAA.

AT+MODE=OTAA

Práce s knihovnou OpenCV

Knihovna OpenCV je určená pro práci s obrázky v jazyce C/C++. Přesto že knihovna podporuje mnoho složitých funkcí v základu je její použití velmi jednoduché.

Na internetu je možné o této knihovně nalézt mnoho informací. Projekt samotný je k dispozici na stránkách http://opencv.org/ .

Pro správnou funkci OpenCV je nutné vložit následující hlavičkové soubory:

#include "opencv2\opencv.hpp"

V programu je nutné vytvořit instanci třídy Mat, která reprezentuje obrázek. Tento obrázek je poté možné buď načíst nebo vytvořit.

Mat bgr_img = imread( filename, CV_LOAD_IMAGE_COLOR );     //načtení obrázku ze souboru
Mat bgr_img = imread( filename, CV_LOAD_IMAGE_UNCHANGED ); //načtení obrázku ze souboru včetně alfa kanálu
Mat img( SIZEY, SIZEX, CV_8UC1 );                          //vytvoření obrázku B/W, bez alfa kanálu 
Mat img( SIZEY, SIZEX, CV_8UC3 );                          //vytvoření obrázku RGB, bez alfa kanálu 
Mat img( SIZEY, SIZEX, CV_8UC4 );                          //vytvoření obrázku RGB, včetně alfa kanálu

int bytes = img.channels();                                //hloubka obrazu, počet bajtů na pixel
void * data_obrazu = img.data;                             //sekvence bajtů reprezentující obrázek

Z objektu reprezentující obrázek lze vyčíst různé parametry obrázku. Jako například výšku a šířku.

 Size bgr_img_size = bgr_img.size();
 int sizex = bgr_img_size.width;           //šířka
 int sizey = bgr_img_size.height           //výška

Alternativně je možné použít:

 int sizex = bgr_img.cols;                 //šířka
 int sizey = bgr_img.rows;                 //výška

Vlastnosti jednotlivých pixelů, tedy hodnoty složek R,G a B je možné získat z objektu Mat dvojím způsobem.
Pomocí vektoru knihovny OpenCV - Vec1b, Vec3b a Vec4b:

Vec3b v3 = bgr_img.at<Vec3b>( pozice_y, pozice_x );
printf("B=%d, G=%d, R=%d\n",v3[0],v3[1],v3[2]);

Pomocí CUDA struktur - uchar1, uchar3 a uchar4:

ucha4 u4 = bgr_img.at<uchar4>( pozice_y, pozice_x );
printf("B=%d, G=%d, R=%d, Alfa=%d\n",u4.x,u4.y,u4.z,u4.w);

Opačný postup, tedy nastavení hodnot pixelu lze provést následovně:

Vec3b v3 = { 10, 20, 30 }; //hodnoty R,G a B
bw_img.at<Vec3b>( pozice_y, pozice_x ) = v3;

Obdobně i pro struktury uchar1, uchar3 a uchar4...

Vytvořený obrázek je možné zobrazit pomocí funkce imshow("Název okna",image1). Funkce waitKey(delay) ponechá vykreslené okno do stisku klávesy případně po definovanou dobu v milisekundách, v případě že bude doba rovna 0, bude se čekat jen na stisk klávesy.

imshow( "Obrazek", img );
waitKey( 0 );

Obrázek je také možné uložit pomocí funkce imwrite();

imwrite("nazev_jpg_obrazku.jpg", objekt_mat);
imwrite("nazev_png_obrazku.png", objekt_mat);