{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 9. előadás\n",
    "*Tartalom:* Raspberry Pi: Python GPIO\n",
    "\n",
    "### RaspberryPi: Python GPIO\n",
    "\n",
    "\n",
    "A RaspberryPi (továbbiakban: RPi) egy mikroszámítógép. A tantárgy keretein belül a RPi 3 változatát fogjuk tárgyalni. Ennek is két fajtája a létezik, a RPi 3B (régebbi) és a RPi 3B+ (újabb). Az előadás szempontjától nem teszünk lényeges különbséget a kettő között. \n",
    "\n",
    "A két modell bemutató videója az alábbi linkeken található: \n",
    "[RPi 3B](https://www.youtube.com/watch?v=uXUjwk2-qx4) és\n",
    "[RPi 3B+](https://www.youtube.com/watch?v=i62xdD4QKtA)\n",
    "\n",
    "#### A RPi 3B specifikációja\n",
    "\n",
    "- Quad Core 1.2GHz BCM2837 CPU - 64bit\n",
    "- 1GB SDRAM\n",
    "- BCM43143 WiFi & Bluetooth Low Energy\n",
    "- Wi-fi (802.11 b/g/n, 2,4 GHz)\n",
    "- Bluetooth 4.1 Classic, Bluetooth Low Energy\n",
    "- 40pin-es kiterjesztett GPIO\n",
    "- 4 x USB 2.0 port\n",
    "- 4 pólusú jack a sztereó hang és kompozit videó kimenethez\n",
    "- HDMI kimenet\n",
    "- CSI kamera port csatlakozó a Raspberry Pi kamera részére\n",
    "- DSI Display Port csatlakozó érintőképernyőhöz\n",
    "- Micro SD kártya csatlakozó az operációs rendszer betöltéséhez és az adatok tárolására\n",
    "- Javasolt tápegység minimum 1.2A 5V, de maximum 2.5A 5.1V\n",
    "- Micro USB-s tápcsatlakozás maximum 2.5A 5.1V - nagyobb átfolyó áramtól a csatlakozók, illetve a nyomtatott áramköri hutalozás maradandóan károsodhat, ezért több, vagy nagyobb fogyasztású külső eszköznek érdemes direkt tápellátást biztosítani!\n",
    "- Mechanikai kompatibilitás a B+ és Pi 2 verziókkal\n",
    "\n",
    "#### A RPi 3B+ specifikációja\n",
    "\n",
    "- CPU: Broadcom BCM2837B0, Cortex-A53 64-bit SoC @ 1.4GHz - 10%-al gyorsabb a sima Pi 3-nál, meglátjuk majd, hogy mire elég.\n",
    "- Memória: 1GB LPDDR2 SDRAM - ez változatlan\n",
    "- Wifi: IEEE 802.11 b/g/n/ac szabványú kétsávos rendszer (2.4 GHz és 5GHz) - ez egy ütős változás!\n",
    "- LAN: Gigabit Ethernet (Microchip LAN7515), ami jelen esetben max. 300Mbps - ez háromszorosa a korábbi verziókénak, végre!!!\n",
    "- USB: 4x USB 2.0 - sokan várnák az USB 3-as csatlakozást, de az indokolatlanul drágítaná az eszközt.\n",
    "- GPIO: a Pi 1 B+ óta megszokott 40-pin, hála a tervezőknek.\n",
    "- Videó és hang (ez sem módosult):\n",
    "    - HDMI kimenet\n",
    "    - MIPI DSI display port\n",
    "    - MIPI CSI kamera port\n",
    "    - 4 pólusú 3.5mm-es jack aljzaton sztereó hang és kompozit videó kimenet\n",
    "- Multimédia képességek: H.264, MPEG-4 dekóder (1080p30); H.264 enkóder (1080p30); OpenGL ES 1.1, 2.0 grafikus gyorsítás\n",
    "- SD kártya támogatás: Micro SD támogatás az operációs rendszer futtatásához és adattároláshoz\n",
    "- Tápellátási lehetőségek:\n",
    "    - 5Vdc/2.5A (max.) micro USB csatlakozón keresztül\n",
    "    - 5Vdc GPIO tüskéken át\n",
    "    - PoE (Power over Ethernet) lehetőség megfelelő HAT alkalmazásával\n",
    "- Működési hőmérséklet tartomány: 0-50°C között\n",
    "\n",
    "\n",
    "#### Operációs rendszer\n",
    "\n",
    "Alapvetően a kezdők számára javasolt és megvásárolható egy előre telepített SD kártya, amely tartalmaz egy ún. NOOBS (New Out Of Box System) rendszert. Ez egy telepítő-menedzser, amely könnyebbé teszi az operációs rendszer telepítését. A haladó felhasználók letölthetik a NOOBS-ot [INNEN](https://www.raspberrypi.org/downloads/) és telepíthetik azt egy üres SD kártyára. Erről részletesebb leírás [ITT](https://www.raspberrypi.org/documentation/installation/noobs.md) és [ITT](https://projects.raspberrypi.org/en/projects/raspberry-pi-setting-up) található. \n",
    "\n",
    "A NOOBS tartalmazza az alábbi operációs rendszerek telepítését: \n",
    "- Raspbian\n",
    "- LibreELEC\n",
    "- OSMC\n",
    "- Recalbox\n",
    "- Lakka\n",
    "- RISC OS\n",
    "- Screenly OSE\n",
    "- Windows 10 IoT Core\n",
    "- TLXOS\n",
    "\n",
    "Bár alapvetően a NOOBS csak a Raspbian és LibreELEC rendszerek telepítőcsomagját tartalmazza, a többi rendszer választásakor rendelkeznünk kell internet kapcsolattal, ahonnan letöltődik a kívánt csomag.\n",
    "\n",
    "A RPi optimális működéshez Raspbian rendszer javasolt, amely egy Debian-alapú Linux. Sajnos a RPi 3B+ nem támogatja az Ubuntu kernelt, így az Ubuntu MATE és Ubuntu Core rendszerek csak a sima RPi 3 és RPi 2 változatokon használhatók.\n",
    "\n",
    "\n",
    "#### Bootolási módok\n",
    "\n",
    "A RPi számos bootolási lehetőséget nyújt:\n",
    "- Bootflow: Boot sequence description; részletesebben [ITT](https://www.raspberrypi.org/documentation/hardware/raspberrypi/bootmodes/bootflow.md) \n",
    "- SD card: SD card boot description; korábban szó volt róla\n",
    "- USB: USB boot description\n",
    "    - Device boot: Booting as a mass storage device; részletesebben [ITT](https://www.raspberrypi.org/documentation/hardware/raspberrypi/bootmodes/device.md)\n",
    "    - Host boot: Booting as a USB host; részletesebben [ITT](https://www.raspberrypi.org/documentation/hardware/raspberrypi/bootmodes/host.md)\n",
    "    - Mass storage boot: Boot from Mass Storage Device (MSD); részletesebben [ITT](https://www.raspberrypi.org/documentation/hardware/raspberrypi/bootmodes/msd.md)\n",
    "    - Network boot: Boot from ethernet; részletesebben [ITT](https://www.raspberrypi.org/documentation/hardware/raspberrypi/bootmodes/net.md)\n",
    "    \n",
    "A régebbi RPi változatoknál, valamint azokban az esetekben amikor a RPi 3 bootolása valami miatt meghiúsul, újfajta bootolási módszereket vezettek be, ezek az MSD és az Ethernet. Ehhez nem kell mást tenni, mint FAT32 formátumra formázni az SD kártyát és rámásolni a legfrisebb [bootcode.bin](https://github.com/raspberrypi/firmware/raw/master/boot/bootcode.bin) fájlt. Ez bekapcsolja az új boot módokat, valamint bug fixeket tartalmaz a bootolási meghiúsulások kiküszöbölésére.   "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Python GPIO\n",
    "\n",
    "A GPIO (General Purpose Input Output) egy általános felhasználású port, ahogy a neve is sugallja, mellyel különféle kimeneti és bemeneti jeleket tudunk manipulálni. A RPi GPIO lábkiosztása az alábbi képen látható:\n",
    "\n",
    "\n",
    "![A Raspberry Pi GPIO kiostása](data/raspberry-pi-gpio-pins.png)\n",
    "\n",
    "\n",
    "Látható, hogy csak a zölddel jelölt lábak használhatók teljes mértékben GPIO-ként, a sárgával jelölt lábak csak bizonyos feltétel mellett, és a pirosak egyáltalán nem. Ez utóbbiak főként tápegység kimenetként működnek, melyek értéke általában 3.3V és 5V. Ezeken kívűl a feketével jelölt lábak földellésként viselkednek, jelölésük a GND (Ground).\n",
    "\n",
    "Ahhoz, hogy használhassuk a RPi GPIO portját, fel kell telepíteni a hozzá tartozó csomagot, melyet az alábbi parancssori parancsok futtatásával tehetünk meg:\n",
    "\n",
    "`sudo apt-get update`\n",
    "\n",
    "`sudo apt-get upgrade`\n",
    "\n",
    "`sudo apt-get install rpi.gpio` vagy haladóknak `sudo pip install RPi.GPIO`\n",
    "\n",
    "Ezután ahhoz, hogy használni tudjuk a GPIO-t, importálni kell a megfelelő python könyvtárat a kódunkba:\n",
    "\n",
    "`import RPi.GPIO as GPIO`\n",
    "\n",
    "Ezt követően inicializálnunk kell a GPIO-t:\n",
    "\n",
    "`GPIO.setmode(GPIO.BOARD)` vagy `GPIO.setmode(GPIO.BCM)`\n",
    "\n",
    "Mi a különbség a kettő között?\n",
    "1. A GPIO.BOARD arra utal, hogy a lábakat a panelen levő sorszámozás alapján fogjuk használni. Ez a sorszámozás úgy néz ki, hogy a bal felső láb az 1-es, a mellette levő a 2-es, alattal evő sorban a 3-4-es, és így tovább lefele haladva. Ld.:\n",
    "        1  2\n",
    "        3  4\n",
    "        5  6\n",
    "        .  .\n",
    "        .  .\n",
    "        .  .\n",
    "        39 40\n",
    "2. A GPIO.BCM pedig arra utal, hogy a Broadcom SOC channel által elnevezett nevekkel fogunk hivatkozni az egyes lábakra. Ezek azok a nevek, amelyek a fenti képen is szereplnek. Pl. GPIO4, GPIO5, stb.\n",
    "\n",
    "Mostmár készen állunk a GPIO lábak használatára, akár kimenetként vagy bemenetként, akár valamilyen logikai értékként, stb. Nézzünk néhány konkrét példát:\n",
    "\n",
    "`GPIO.setup(12, GPIO.OUT)` # ez a parancs a 12-es lábat állítja be kimenetként a setup() metódus segítségével\n",
    "\n",
    "`GPIO.output(12, GPIO.HIGH)` # ezzel a 12-es lábat logikai magas szintre állítjuk, ami 3,3V\n",
    "\n",
    "`GPIO.output(12, GPIO.LOW)` # ezzel viszont logikai alacsony szintre állítjuk, ami 0V\n",
    "\n",
    "\n",
    "Ahhoz, hogy akármilyen szerzort vagy aktuátort vezéreljünk, szükségünk lesz egy ún. \"breadboard\"-ra. Egy ilyen kellék és a kötési módja az alábbi képen látható:\n",
    "\n",
    "![Breadboard](data/breadboard-connections.png)\n",
    "\n",
    "A középen levő két oszlop lyukai vízszintes irányban képeznek kapcsolatot, míg a szélén levő két vonalban helyezkedő lyukak hosszanti irányba képeznek kapcsolatot, ahogyan be is vannak keretezve.\n",
    "\n",
    "Nézzünk egy egyszerű LED villogtató példát:\n",
    "\n",
    "A LED egy kétutas félvezető, amely a rákapcsolt feszültség hatására fényt bocsát ki. Mivel a nevében is szerepel, hogy ez egy dióda, ezért csak egy irányba folyik rajta áram. Figyelni kell tehát a kötésmódra. \n",
    "\n",
    "![LED pólusai](data/led.png)\n",
    "\n",
    "Az anódra kerül a pozitív feszültség (3,3V), míg a katódra a földelés (GND). A lábakat úgy tudjuk általában megkülönböztetni, hogy az anód a hosszabb. Továbbá, mivel a GPIO lábak által szolgáltatott 3,3V túl magas a LED-nek, ezért egy ellenállással csökkentjük a LED-re eső feszültséget. A LED-nek 2,1V feszültségre és kb. 20mA áramra van szüksége a működéshez. A GPIO lábak azonban 3,3V feszültséget és csak 16mA áramot szolgáltanak. Nézzük hát a képletet, amivel kiszámolhatjuk a szükséges ellenállás méretét:\n",
    "\n",
    "\\begin{equation*}\n",
    "R = \\frac{U}{I} = \\frac{3.3V-2.1V}{16mA} = \\frac{1.2V}{0.016A} = 75\\Omega\n",
    "\\end{equation*}\n",
    "\n",
    "Mivel a piaci forgalomban a 75Ω-os ellenállás speciális értékűnek minősül, és általában drágábbak, vagy csak nagyobb tételben vásárolható, ezért számunkra tökéletesen megfelel a sima 82Ω-os, elektronikai szaküzletekben kapható ellenállás.\n",
    "\n",
    "Miután tehát összekötöttük az áramkört az alábbi képen látható módon, megírhatjuk hozzá a vezérlő Python kódot.\n",
    "\n",
    "![LED kötési rajza](data/led_circuit.png)\n",
    "\n",
    "```\n",
    "import RPi.GPIO as GPIO\n",
    "import time\n",
    "\n",
    "GPIO.setmode(GPIO.BOARD)\n",
    "GPIO.setup(12, GPIO.OUT)\n",
    "\n",
    "GPIO.output(12, GPIO.HIGH)\n",
    "time.sleep(3)\n",
    "\n",
    "GPIO.output(12, GPIO.LOW)\n",
    "GPIO.cleanup()\n",
    "```\n",
    "\n",
    "A gyakorlatban, amikor már nem használjuk tovább a GPIO lábakat, resetelni szoktuk azokat a `cleanup()` metódussal. \n",
    "\n",
    "##### Olvasás a bemenetről\n",
    "\n",
    "Hasonlóan, ahogy kimenetként definiáltuk az előbb a GPIO lábat, bemenetként is definiálhatjuk azt:\n",
    "\n",
    "`GPIO.setup(11, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)`\n",
    "\n",
    "Látjuk, hogy egy teljesen új `pull_up_down` argumentum került bevezetésre, ezt kicsit lentebb magyarázzuk. Az bemenetről való olvasáshoz az `input()` metódust használjuk, és ez a `GPIO.HIGH` vagy `GPIO.LOW` értékeket adja vissza számunkra, attól függően, hogy a bemenetünk aktív, vagy sem.\n",
    "\n",
    "`GPIO.input(11)`\n",
    "\n",
    "Térjünk kicsit vissza a korábban bevezett `pull_up_down` argumentumra. Ennek értékeit az alábbi táblázat magyarázza: \n",
    "\n",
    "| Érték | +3.3V | <+3.3V | 0V |\n",
    "| :----- | :-----: | :-----: | :-----: |\n",
    "| `GPIO.PUD_DOWN` | Aktív | Inaktív | Inaktív |\n",
    "| `GPIO.PUD_UP` | Inaktív | Aktív | Aktív |\n",
    "\n",
    "Nézzünk erre is egy példát, az előző feladatot egy nyomógobbal kiegészítve. Akkor fog tehát a LED világítani, ha megnyomjuk a nyomógombot. Nézzük, hogyan fog kinézni ennek a kötési rajza:\n",
    "\n",
    "![Nyomógombos LED villogtatás](data/led_button_circuit.png)\n",
    "\n",
    "```\n",
    "import RPi.GPIO as GPIO\n",
    "\n",
    "GPIO.setmode(GPIO.BOARD)\n",
    "\n",
    "GPIO.setup(12, GPIO.OUT)\n",
    "GPIO.setup(11, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)\n",
    "GPIO.output(12, GPIO.LOW)\n",
    "\n",
    "try:\n",
    "    while True:\n",
    "        GPIO.output(12, GPIO.input(11))\n",
    "except KeyboardInterrupt:\n",
    "    GPIO.cleanup()\n",
    "```\n",
    "\n",
    "Látható a kódból, hogy a 12-es lábra kötött LED akkor lesz `GPIO.HIGH` értéken, amikor a `GPIO.input(11)` aktívvá válik, vagyis lenyomtuk a nyomógombot.\n",
    "\n",
    "#### Házi feladat\n",
    "\n",
    "Fejlesszék tovább a legelső LED-es feladatot, hogy a LED egyfolytában villogjon 1 mp-s szünetekkel.\n",
    "\n",
    "\n",
    "## A Sense Hat\n",
    "\n",
    "A Sense Hat egy olyan bővítő modul a RPi-hez, amely különféle szenzorokat, LED-mátrixot és joysticket is tartalmaz. Lássuk milyen szenzorkészlettel rendelkezik:\n",
    "- hőmérséklet\n",
    "- páratartalom\n",
    "- nyomás\n",
    "- orientáció\n",
    "\n",
    "Ahhoz, hogy kapcsolatunk legyen a Sense Hat-el, be kell illesztenünk a megfelelő könytárat a Python kódunkba. Ez az alábbi sorokkal történik:\n",
    "\n",
    "`from sense_hat import SenseHat`\n",
    "`sense = SenseHat()`\n",
    "\n",
    "### Szöveg megjelenítése a LED kijelzőn\n",
    "\n",
    "Ahhoz, hogy valamilyen szöveget - legyen az egy karakter, vagy sztring - megjelenítsünk a LED-es kijelzőn, használhatjuk a `show_message(\"Hello World\")` vagy `show_letter(\"A\")` függvényeket.\n",
    "Különféle megjelenítési tulajdonságokat is hozzá adhatunk a kiíró metódushoz, melyeket paramétereknek nevezünk:\n",
    "- scroll_speed: azt mondja meg, milyen gyorsan haladjon át a szöveg a kijelzőn. Default: 0.1\n",
    "- text_colour: a szöveg színét definiálja, három szín értékkel: RGB.\n",
    "- back_colour: ugyanúgy definiálandó, mint a text_colour, de ez a háttér színét határozza meg.\n",
    "\n",
    "\n",
    "#### Szöveg megjelenítése a LED kijelzőn\n",
    "\n",
    "Nézzük meg konkrét példán keresztül. Írassuk ki a \"Hello World!\" szöveget ciklikusan, piros színnel, kék háttéren, és 0.05 átfutási sebességgel.\n",
    "\n",
    "```\n",
    "from sense_hat import SenseHat\n",
    "sense = SenseHat()\n",
    "\n",
    "blue = (0, 0, 255)\n",
    "red = (255, 0, 0)\n",
    "\n",
    "while True:\n",
    "  sense.show_message(\"Hello World!\", text_colour=red, back_colour=blue, scroll_speed=0.05)\n",
    "```\n",
    "\n",
    "#### Egy darab karakter megjelenítése a LED kijelzőn\n",
    "\n",
    "Nézzük meg ezt is példán keresztül. Írassuk ki a Széchenyi Egyetem kezdőbetűit, azaz a SZE betűket, ahol \"S\" sárga, \"Z\" fehér, \"E\" kék, a háttér cián, és a betűk megjelenítési közötti szünet 2 mp. Ehhez szükségünk lesz a `time` könyvtár `sleep()` függvényére is. A végén pedig a `clear()` metódussal töröljük a képernyőt.\n",
    "\n",
    "```\n",
    "from sense_hat import SenseHat\n",
    "from time import sleep\n",
    "\n",
    "sense = SenseHat()\n",
    "\n",
    "cyan = (0, 255, 255)\n",
    "blue = (0, 0, 255)\n",
    "white = (255, 255, 255)\n",
    "yellow = (255, 255, 0)\n",
    "\n",
    "sense.show_letter(\"S\", yellow, back_colour=cyan)\n",
    "sleep(2)\n",
    "sense.show_letter(\"Z\", white, back_colour=cyan)\n",
    "sleep(2)\n",
    "sense.show_letter(\"E\", blue, back_colour=cyan)\n",
    "sleep(2)\n",
    "sense.clear()\n",
    "```\n",
    "\n",
    "Következőnek generáljunk random színeket és így írassuk ki a \"SZE\" betűket. Ehhez létrehozunk egy függvényt, valamint szükségünk lesz a `randint()` metódusra is.\n",
    "\n",
    "```\n",
    "from sense_hat import SenseHat\n",
    "from time import sleep\n",
    "from random import randint\n",
    "\n",
    "sense = SenseHat()\n",
    "\n",
    "def pick_random_colour():\n",
    "  random_red = randint(0, 255)\n",
    "  random_green = randint(0, 255)\n",
    "  random_blue = randint(0, 255)\n",
    "  return (random_red, random_green, random_blue)\n",
    "\n",
    "sense.show_letter(\"S\", pick_random_colour())\n",
    "sleep(2)\n",
    "sense.show_letter(\"Z\", pick_random_colour())\n",
    "sleep(2)\n",
    "sense.show_letter(\"E\", pick_random_colour())\n",
    "sleep(2)\n",
    "\n",
    "sense.clear()\n",
    "```\n",
    "\n",
    "### Kép megjelenítése a LED kijelzőn\n",
    "\n",
    "Lehetőség van a kijelzőn képeket is megjeleníteni. Ennek a legprimitívebb változata, amikor egyszínűre fessük a teljes LED mátrixot:\n",
    "\n",
    "`sense.clear((r, g, b))`\n",
    "\n",
    "Továbbá, lehetőségünk van az egyes pixeleket (LEDeket) is befesteni. Minden pixelnek megvan a saját {x,y} koordinátája, amely a bal felső sarokból kezdődik {0,0}-val. Az indexelés az alábbi képen látható:\n",
    "\n",
    "![LED mátrix koordinátái](data/coordinates.png)\n",
    "\n",
    "A pixelek színeit a `set_pixel(x, y, colour)` metódussal tudjuk. Nézzünk erre is egy egyszerű kis példát:\n",
    "\n",
    "```\n",
    "from sense_hat import SenseHat\n",
    "sense = SenseHat()\n",
    "\n",
    "blue = (0, 0, 255)\n",
    "red = (255, 0, 0)\n",
    "\n",
    "sense.set_pixel(0, 2, blue)\n",
    "sense.set_pixel(7, 4, red)\n",
    "```\n",
    "\n",
    "Egyszerre több pixelt is kezelhetünk a `set_pixels` paranccsal, amennyiben egy tömbbe tároljuk el az egyes pixelek értékeit. Nézzük, hogyan:\n",
    "\n",
    "```\n",
    "g = (0, 255, 0) # Green\n",
    "b = (0, 0, 0) # Black\n",
    "\n",
    "pixels = [\n",
    "    g, g, g, g, g, g, g, g,\n",
    "    g, g, g, g, g, g, g, g,\n",
    "    g, b, b, g, g, b, b, g,\n",
    "    g, b, b, g, g, b, b, g,\n",
    "    g, g, g, b, b, g, g, g,\n",
    "    g, g, b, b, b, b, g, g,\n",
    "    g, g, b, b, b, b, g, g,\n",
    "    g, g, b, g, g, b, g, g\n",
    "]\n",
    "\n",
    "sense.set_pixels(pixels)\n",
    "```\n",
    "\n",
    "### Az érzékelők használata\n",
    "\n",
    "A nyomásérzékelőt a `sense.get_pressure()` metódussal tudjuk lekérdezni.\n",
    "\n",
    "```\n",
    "from sense_hat import SenseHat\n",
    "\n",
    "sense = SenseHat()\n",
    "sense.clear()\n",
    "\n",
    "pressure = sense.get_pressure()\n",
    "print(pressure)\n",
    "```\n",
    "Output: 1012.97997042\n",
    "\n",
    "__________________________________________________________________\n",
    "\n",
    "A páratartalmat a `get_humidity()` metódussal tudjuk lekérdezni.\n",
    "\n",
    "```\n",
    "from sense_hat import SenseHat\n",
    "\n",
    "sense = SenseHat()\n",
    "sense.clear()\n",
    "\n",
    "humidity = sense.get_humidity()\n",
    "print(humidity)\n",
    "```\n",
    "\n",
    "Output: 45.2721951219\n",
    "\n",
    "__________________________________________________________________\n",
    "\n",
    "A hőmérsékletet alapesetben a `get_temperature()` metódussal kérdezzük le.\n",
    "\n",
    "```\n",
    "from sense_hat import SenseHat\n",
    "\n",
    "sense = SenseHat()\n",
    "sense.clear()\n",
    "\n",
    "temp = sense.get_temperature()\n",
    "print(temp)\n",
    "```\n",
    "Output: 19.9493634245\n",
    "\n",
    "Itt viszont vigyázni kell a RPi processzor melegedéséből fakadó hibára. Mivel a processzor felmelegíti a szenzorokat is, főleg ha dobozban helyezkednek, ezért kalibrációt kell végezni a pontos hőmérséklet mérés érdekében.\n",
    "\n",
    "Ennek a képlete az alábbi:\n",
    "\n",
    "\\begin{equation*}\n",
    "T_{kalibrált} = T_{mért} - \\frac{T_{cpu} - T_{mért}}{Koefficiens}\n",
    "\\end{equation*}\n",
    "\n",
    "ahol a Koefficienst külső mérésekre alapozva kell meghatározni úgy, hogy a kalibrált érték a legközelebb álljon a környezet valós hőmérsékletéhez.\n",
    "\n",
    "\n",
    "### Orientáció meghatározása\n",
    "\n",
    "A mozgások meghatározására a Sense Hat rendelkezik egy ún. IMU-val (Innertial Measurement Unit), vagyis innerciális mérés-egységgel. Az ilyen egységek általában háromféle szenzorból állnak:\n",
    "- gyorsulásmérő (gyorsulási erőt érzékel)\n",
    "- giroszkóp (tájolást érzékel)\n",
    "- magnetométer (a Föld mágneses terét érzékeli)\n",
    "\n",
    "Amikor meghívjuk a `get_orientation()` metódust, ez három adatot szolgáltat számunkra:\n",
    "- pitch: dőlés\n",
    "- roll: perdülés\n",
    "- yaw: irányváltoztatás\n",
    "\n",
    "A szemléltetés kedvéért az alábbi képen látható a három mozgás tengelye.\n",
    "\n",
    "![3-tengelyes mozgás](data/oreantation.png)\n",
    "\n",
    "Nézzük meg egy példán keresztül, milyen adatokat kapunk.\n",
    "\n",
    "```\n",
    "from sense_hat import SenseHat\n",
    "sense = SenseHat()\n",
    "sense.clear()\n",
    "\n",
    "o = sense.get_orientation()\n",
    "pitch = o[\"pitch\"]\n",
    "roll = o[\"roll\"]\n",
    "yaw = o[\"yaw\"]\n",
    "print(\"pitch {0} roll {1} yaw {2}\".format(pitch, roll, yaw))\n",
    "```\n",
    "\n",
    "Output: pitch 356.35723002363454 roll 303.4986602798494 yaw 339.19880231669873\n",
    "\n",
    "_________________________________________________________________________________\n",
    "\n",
    "A `get_accelerometer_raw()` metódus segítségével nyers adatokat kaphatunk a gravitációs erőnk hatásáról az egyes tengelyekre (x, y, z) nézve. Ha pl. bármelyik tengelyen a gravitációs erőnk &pm;1G, akkor tudjuk, hogy ez a tengely lefelé mutat. A következő példában az összes tengelyre nézve lekérdezzük a gravitációs gyorsulást, majd a legközelebbi egész számra kerekítjük.\n",
    "\n",
    "\n",
    "```\n",
    "from sense_hat import SenseHat\n",
    "\n",
    "sense = SenseHat()\n",
    "\n",
    "while True:\n",
    "\tacceleration = sense.get_accelerometer_raw()\n",
    "\tx = acceleration['x']\n",
    "\ty = acceleration['y']\n",
    "\tz = acceleration['z']\n",
    "\n",
    "\tx=round(x, 0)\n",
    "\ty=round(y, 0)\n",
    "\tz=round(z, 0)\n",
    "\n",
    "\tprint(\"x={0}, y={1}, z={2}\".format(x, y, z))\n",
    "```\n",
    "Vízszintes tengelyen elforgatva a Sense Hatet, azt látjuk, hogy a \"x\" és \"y\" tengelyek értékei {-1, 1} között változnak. Ha pedig függőleges irányban forgatjuk el egy &pi; (180&deg;) értékkel, akkor a \"z\" tengely értéke fog {1, -1} között változni.\n",
    "\n",
    "\n",
    "### A joystick használata\n",
    "\n",
    "Öt féle irányba használhatjuk a Sense Hat joystickjét, lefele (lenyomni), előre, hátra, jobbra, balra. Ezen felül érzékelhetjük a lenyomást, a lenyomva tartást és a felengedést is. A következő példában írassuk ki a joystick éppen aktuális állapotát.\n",
    "\n",
    "```\n",
    "from sense_hat import SenseHat\n",
    "  sense = SenseHat()\n",
    "\n",
    "\n",
    "  while True:\n",
    "      for event in sense.stick.get_events():\n",
    "          print(event.direction, event.action)\n",
    "```\n",
    "\n",
    "Erre a joystick mozgatása közben valami hasonlót kell kapnunk:\n",
    "\n",
    "('up', 'pressed')\n",
    "('up', 'released')\n",
    "('down', 'pressed')\n",
    "('down', 'released')\n",
    "('left', 'pressed')\n",
    "('left', 'released')\n",
    "('right', 'pressed')\n",
    "('right', 'released')\n",
    "('middle', 'pressed')\n",
    "('middle', 'released')\n",
    "\n",
    "____________________________________________________________________________\n",
    "\n",
    "Készítsünk egy olyan programot, amely a megnyomott irányoktól függően kiírja a LED mátrixra a megfelelő irány kezdőbetűjét. \n",
    "\n",
    "```\n",
    "from sense_hat import SenseHat\n",
    "from time import sleep\n",
    "sense = SenseHat()\n",
    "\n",
    "while True:\n",
    "  for event in sense.stick.get_events():\n",
    "    if event.action == \"pressed\":\n",
    "            \n",
    "      if event.direction == \"up\":\n",
    "        sense.show_letter(\"F\")      # Fel\n",
    "      elif event.direction == \"down\":\n",
    "        sense.show_letter(\"L\")      # Le\n",
    "      elif event.direction == \"left\": \n",
    "        sense.show_letter(\"B\")      # Bal\n",
    "      elif event.direction == \"right\":\n",
    "        sense.show_letter(\"J\")      # Jobb\n",
    "      elif event.direction == \"middle\":\n",
    "        sense.show_letter(\"K\")      # Közép\n",
    "\n",
    "      sleep(0.5)\n",
    "      sense.clear()\n",
    "```\n",
    "\n",
    "______________________________________________________________________________________________________\n",
    "\n",
    "## _Used sources_ / Felhasznált források\n",
    "- [Shannon Turner: Python lessons repository](https://github.com/shannonturner/python-lessons) MIT license (c) Shannon Turner 2013-2014\n",
    "- [Siki Zoltán: Python mogyoróhéjban](http://www.agt.bme.hu/gis/python/python_oktato.pdf) GNU FDL license (c) Siki Zoltán\n",
    "- [BME AUT](https://github.com/bmeaut) MIT License Copyright (c) BME AUT 2016-2018\n",
    "- [Python Programming](https://pythonprogramming.net) (c) OVER 9000! PythonProgramming.net\n",
    "- [Raspberry Pi Foundation](https://github.com/RPi-Distro/python-sense-hat) Copyright 2015- Raspberry Pi Foundation"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}