{"id":444,"date":"2019-01-03T10:41:47","date_gmt":"2019-01-03T08:41:47","guid":{"rendered":"https:\/\/iot.ttu.ee\/et\/?p=444"},"modified":"2019-01-03T10:42:13","modified_gmt":"2019-01-03T08:42:13","slug":"nutimaja-ehitamine-tarkvara","status":"publish","type":"post","link":"https:\/\/iot.ttu.ee\/et\/nutimaja-ehitamine-tarkvara\/","title":{"rendered":"Nutimaja ehitamine: tarkvara"},"content":{"rendered":"<p>J\u00e4rgnev blogipostitus on j\u00e4tk nutimaja ehitamise sarjale. Kui aga eelnev peat\u00fckk riistvara ehitamise teemal j\u00e4i mingil p\u00f5hjusel vahele, siis saab seda lugeda <a href=\"https:\/\/iot.ttu.ee\/et\/opetus-riistvara\/\">siin<\/a>.<\/p>\n<p><strong>Sisukord<\/strong><\/p>\n<ol>\n<li>Programmeerimiskeskkonna \u00fclesseadmine<\/li>\n<li>Esimesed sammud universaalportidega<\/li>\n<li>Liikumise peale valgusti juhtimine<\/li>\n<li>Valgusti juhtimine m\u00f5nest teisest seadmest (nt nutitelefonist)<\/li>\n<li>Kuhu edasi?<\/li>\n<\/ol>\n<p><strong>T\u00f6\u00f6vahendid<\/strong><\/p>\n<ol>\n<li>Raspberry Pi 3B+*<\/li>\n<li>SD m\u00e4lukaart<\/li>\n<li>HDMI kaabel<\/li>\n<li>Hiir<\/li>\n<li>Klaviatuur<\/li>\n<li>Monitor HDMI toega<\/li>\n<li>Kohtv\u00f5rk<\/li>\n<li>Etherneti kaabel (valikuline)<\/li>\n<\/ol>\n<p>* Tegelikult sobib \u00fcksk\u00f5ik milline versioon. Konkreetse ettev\u00f5tmise jaoks v\u00f5ivad erinevuseks olla GPIO viikude asukohad ja numbrid, mist\u00f5ttu tuleks \u00fchendamisel \u00fcle kontrollida vastavad t\u00e4histused paigutusplaanist (<em>pin layout<\/em>).<\/p>\n<p><strong>Eelt\u00f6\u00f6<\/strong><\/p>\n<p>Selleks, et alustada Raspberry Pi peal programmeerimisega, tuleb \u00fcles seada vastav keskkond. Kuna aga Raspberry Pi sarnaneb oma omadustelt pigem miniarvutiga, siis alustame lisakomponentide (monitor, klaviatuur, hiir) \u00fchendamisega ning operatsioonis\u00fcsteemi paigaldamisega. K\u00f5ige lihtsam on seda teha tootja poolse <em>step by step<\/em>\u00a0juhendi j\u00e4rgi, mille leiab <a href=\"https:\/\/projects.raspberrypi.org\/en\/projects\/raspberry-pi-getting-started\">siin<\/a>.<\/p>\n<p>Et olla kindlalt veendunud, et k\u00f5ik vajalikud t\u00f6\u00f6riistad meie projekti jaoks oleksid olemas, siis soovitame k\u00e4sureale (mille saab avada kl\u00f5psates <em>Menu<\/em>-><em>Accessories<\/em>-><em>Terminal <\/em>v\u00f5i \u00fcle <a href=\"https:\/\/www.raspberrypi.org\/documentation\/remote-access\/ssh\/\">SSH<\/a>) anda j\u00e4rgmise \u00fclesande:<\/p>\n<p><code>sudo apt-get -y install python python-dev python-rpi.gpio<\/code><\/p>\n<p><strong>Esimesed sammud universaalportidega (GPIO)<\/strong><\/p>\n<p>Meie esimeseks \u00fclesandeks on luua programm, mis vilgutaks eelmises blogipostituses paigaldatud leedi sisse-v\u00e4lja. Lisaks meie kirjutatud koodijuppidele, saab Python kohta rohkem uudistada\u00a0<a href=\"https:\/\/www.w3schools.com\/python\/\">W3Schools tasuta \u00f5ppekeskkonnas<\/a>.<\/p>\n<p>Igasugune programmeerimist\u00f6\u00f6 algab alati faili tekitamisega, mille saab luua k\u00e4surealt j\u00e4rgmiselt:<\/p>\n<p><code>nano led_vilgutus.py<\/code><\/p>\n<p>Seej\u00e4rel kopeerime aknasse j\u00e4rgneva sisu:<\/p>\n<pre><code class=\"python\"># coding=utf-8 # \u00fctleme programmile, kuidas on tekst esitletud\n\n# \"#\" t\u00e4hem\u00e4rk viitab kommentaari algusele, mis omakorda t\u00e4hendab, sellele j\u00e4rgnev tekst kuni\n# uue rea alguseni ei ole m\u00f5eldud n\u00f6 arvutile t\u00e4itmiseks, vaid lisatakse programmeerijate koodilugemise\n# ja -kirjutamise lihtsustamiseks. Kusjuures sellele tehakse erand, kui esimese kahel real\n# on defineeritud m\u00f5ni teksitvormigu (i.k. encoding) reegel nagu on seda tehtud ka meie n\u00e4ites.\n\nimport RPi.GPIO as GPIO     # \u00fctleme programmile, et soovime universaalportide k\u00e4ske kasutada\nimport time                 # \u00fctleme programmile, et soovime ajaga seotud funktsioone kasutada\n\nLED = 16                    # loome muutuja LED, mille v\u00e4\u00e4rtus on 16, edaspidi programm teab,\n                            # et s\u00f5na \"LED\" t\u00e4hendab arvu 16\n\nGPIO.setmode(GPIO.BCM)      # soovime kasutada universaalporte numbrite j\u00e4rgi\nGPIO.setup(LED, GPIO.OUT)   # soovime 16 GPIO viiku kasutada v\u00e4ljundina\n\nwhile True:                 # tahame ts\u00fcklit, et programm kestaks pidevalt\nGPIO.output(LED, GPIO.HIGH) # anname pinge 16ndale (ehk LED) viigule\nprint(\"Led ON\")             # kirjutame vastave teksti terminali vaatamiseks\ntime.sleep(1)               # puhkame 1 sekundi, programm puhkamise ajal midagi ei tee\nGPIO.output(LED, GPIO.LOW)  # v\u00f5tame pinge \u00e4ra 16ndalt viigult\nprint(\"Led OFF\")\ntime.sleep(1)\n\n<\/code><\/pre>\n<p>Tekstiredaktorist v\u00e4ljumiseks tuleb kasutada klahvikombinatsiooni Cntr+X ning kui programm avaldab soovi salvestamise j\u00e4rele (&#8220;<em>Save modified buffer?<\/em>&#8220;), siis vajutage klahve &#8220;Y&#8221; ja Enter.<\/p>\n<p>Programmi k\u00e4ivitamiseks tuleb anda k\u00e4sklus:<\/p>\n<p><code>python led_vilgutus.py<\/code><\/p>\n<p>Sulgemiseks tuleb vajutada kombinatsiooni Cntr+C.<\/p>\n<p><strong>NB!<\/strong> Kui peaks juhtuma, et mingil p\u00f5hjusel leed ei vilgu, siis esimesena kontrollige \u00fcle universaalpordi number. Seda, kas programm reaalselt pinget v\u00e4ljastab, saab valideerida multimeetri alalispinge m\u00f5\u00f5tmise re\u017eiimis, \u00fchendades selle klemmid leedi &#8220;jalgade&#8221; k\u00fclge.<\/p>\n<p><strong>Liikumise peale valgusti juhtimine<\/strong><\/p>\n<p>Siinkohal v\u00f5tame korra hoo maha ja m\u00f5tleme paremaks arusaamiseks l\u00e4bi, milline peaks olema programmi loogiline t\u00f6\u00f6k\u00e4ik:<\/p>\n<ul>\n<li>Kindlasti peaksime alati programmile sarnaselt eelnenud \u00fclesandele, milliseid (viigu number) ja kuidas (kas lugeda v\u00f5i tekitada pinget) me universaalportide viike kasutada tahame<\/li>\n<li>Kuna PIR andur tekitab oma keskmise v\u00e4ljundviigu peale liikumise korral pinge, siis peaksime sealt tulevat v\u00f5imalikku signaali pidevalt lugema<\/li>\n<li>Kui dekteerime pinge, siis l\u00fclitamine leedi p\u00f5lema ning selle puudumisel kustutame<\/li>\n<\/ul>\n<p>Loome uue faili:<\/p>\n<p><code>nano led_automaatika.py<\/code><\/p>\n<p>&#8230; ja kopeerimine sinna j\u00e4rgneva sisu:<\/p>\n<pre><code class=\"html\"># coding=utf-8  \n\nimport RPi.GPIO as GPIO                 # \u00fctleme programmile, et soovime universaalportide k\u00e4ske kasutada\nimport time                             # \u00fctleme programmile, et soovime ajaga seotud funktsioone kasutada\n\nLED = 16                                # loome muutuja LED, mille v\u00e4\u00e4rtus on 16, edaspidi programm teab,\n                                        # et s\u00f5na \"LED\" t\u00e4hendab arvu 16\n\nPIR_OUTPUT = 18                         # loome muutuja analoogselt LED'ile t\u00e4histamaks GPIO viigu numbrit,\n                                        # millele annab PIR sensori liikumise korral pinge\n\n\nGPIO.setmode(GPIO.BCM)                          # soovime kasutada universaalporte numbrite j\u00e4rgi\nGPIO.setup(LED, GPIO.OUT)                       # soovime 16 GPIO viiku (LED) kasutada v\u00e4ljundina\nGPIO.setup(PIR_OUTPUT, GPIO.IN)                 # soovime 18 GPIO viiku (PIR v\u00e4ljund) lugeda \n                                                # ehk kasutada sisendina\n\nwhile True:                                     # tahame ts\u00fcklit, et programm kestaks pideval\n\n        if GPIO.input(PIR_OUTPUT) == True:      # loeme, kas PIR keskmisel viigul on pinge\n                                                # kui on, siis..\n                GPIO.output(LED, GPIO.HIGH)     # anname pinge 16ndale (ehk LED) viigule, et tekiks valgus\n\n        else:                                   # muul juhul (kui pinget ei olnud), siis ..\n                GPIO.output(LED, GPIO.LOW)      # v\u00f5tame pinge \u00e4ra leedilt, sest liikumist ei ole\n\n<\/code><\/pre>\n<p>Seej\u00e4rel kasutame juba eelnevalt \u00f5pitud salvestamisetehnikat ning k\u00e4ivitame programmi:<\/p>\n<p><code>python led_automaatika.py<\/code><\/p>\n<p><strong>NB!<\/strong> Kui peaks juhtuma, et mingil p\u00f5hjusel leed ei hakka liikumise korral p\u00f5lema, siis esimesena kontrollige \u00fcle universaalportide numbrid. Pingesignaalide olemasolu saab valideerida multimeetri alalispinge m\u00f5\u00f5tmise re\u017eiimis.<\/p>\n<p><strong>Valgusti juhtimine m\u00f5nest teisest seadmest<\/strong><\/p>\n<p>Nagu juba <a href=\"https:\/\/iot.ttu.ee\/et\/sissejuhatus-asjade-internetti\/\">asjade interneti tutvustavas blogiposituses<\/a> vihjasime, tuleb kaugjuhtimiseks luua kahe seadme vaheline \u00fchendus. Antud postituse raames oleva Raspberry Pi 3 puhul saab kasutada nii kaablip\u00f5hist (ethernet) kui ka kaablita (WiFi) l\u00e4henemist kohtv\u00f5rku \u00fchendamiseks. Esimese puhul piisab sellest, kui \u00fchendame seadme etherneti kaabli abil koduruuteri k\u00fclge ning WiFi seadistamiseks leiab asjakohase juhendi\u00a0<a href=\"https:\/\/projects.raspberrypi.org\/en\/projects\/raspberry-pi-getting-started\/7\">siit<\/a>.<\/p>\n<p>\u00dcks lihtsamaid\u00a0(ja seega ka ebaturvalisem l\u00e4henemine) viise kaugjuhtimiseks on kasutada internetibrauserit. Antud projekti raames loome kaks linki, mille kaudu leedi juhtimine toimuma hakkab vastavalt:<\/p>\n<ul>\n<li>http:\/\/\/led_on\u00a0 \u00a0<- sissel\u00fclitamiseks<\/li>\n<li>http:\/\/\/led_off\u00a0 <- v\u00e4ljal\u00fclitamiseks<\/li>\n<\/ul>\n<p>Et suvaline veebibrauseri toega samas kohtv\u00f5rgus olev seade saaks valgusti juhtimise k\u00e4sku edastada, peab meie loodav programm olema v\u00f5imeline kuulama sissetulevaid p\u00e4ringuid. Seda \u00fclesannet oskab lahendada HTTP teenus. HTTP (<em>HyperText Transfer Protocol<\/em>) on veebimaailmas kasutusel olev reeglite kogum, mis m\u00e4\u00e4rab \u00e4ra, kuidas peaksid veebibrauserid ja veebilehek\u00fclgi hoiustavad arvutid (v\u00f5i seadmed) omavahel suhtlema. Selliselt \u00fclesehitusega programmid on asjade interneti maailmas tavaline n\u00e4htus. Lahenduse peamiseks eeliseks on lai \u00fchilduvus, mis v\u00f5imaldab rakendusi lihtsasti programmeerida ja kasutada erinevates seadmetes. Tavaliselt on valmistoodete (n\u00e4iteks m\u00f5ne kodujuhtimise \u00e4ppi puhul) sellised p\u00e4ringud realiseeritud nupuvajutusel n\u00f6 &#8220;tagataustal&#8221;.<\/p>\n<p>Antud juhul saab kasutada leedijuhtimiseks j\u00e4rgnevat koodi:<\/p>\n<pre><code class=\"html\"># coding=utf-8\n\n\nfrom BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer # \u00fctleme programmile, et soovime kasutada \n                                                              # HTTP teenust\nimport RPi.GPIO as GPIO                 # \u00fctleme programmile, et soovime universaalportide k\u00e4ske kasutada\n\nLED = 16                                # loome muutuja LED, mille v\u00e4\u00e4rtus on 16, edaspidi programm teab,\n                                        # et s\u00f5na \"LED\" t\u00e4hendab arvu 16\n\nGPIO.setmode(GPIO.BCM)                  # soovime kasutada universaalporte numbrite j\u00e4rgi\nGPIO.setup(LED, GPIO.OUT)               # soovime 16 GPIO viiku kasutada v\u00e4ljundina\n\nclass Handler(BaseHTTPRequestHandler):     # \u00fctleme programmile, et soovime ise m\u00e4\u00e4rata, mis juhtub p\u00e4ringutel\n    def do_GET(self):                       # \u00fctleme, mida tuleb teha, kui brauser \u00fchendub meie serveri k\u00fclge\n        if self.path == \"\/led_on\":          # mida teha, kui URL on \/led_on l\u00f5puga \n            GPIO.output(LED, GPIO.HIGH)     # anname pinge 16ndale (ehk LED) viigule\n            print(\"LED ON\")\n        elif self.path == \"\/led_off\":       # mida teha, kui URL on \/led_off l\u00f5puga \n            GPIO.output(LED, GPIO.LOW)      # v\u00f5tame pinge \u00e4ra 16ndalt viigult\n            print(\"LED OFF\")\n        self.send_response(200)             # \u00fctleme brauserile, et v\u00f5tsime p\u00e4ringu vastu, just seda\n                                            # t\u00e4histabki kood 200\n\nserver_parameters = ('0.0.0.0', 80)              # p\u00e4ringuid v\u00f5tame vastu Raspberry PI ip aadressil ja pordil 80\nhttpd = HTTPServer(server_parameters, Handler)  # \u00fctleme HTTP teenusele, mis on parameetrid ja kuidas k\u00e4ituda \n                                                 # p\u00e4ringute korral\nhttpd.serve_forever()                            # paneme HTTP teenuse k\u00e4ima\n<\/code><\/pre>\n<p>Et aga mujalt seadmelt ligi saada, peame teadma meie Raspberry Pi IP aadressi. Selle teadasaamiseks saab kasutada terminal k\u00e4sku:<\/p>\n<p><code>hostname -I<\/code><\/p>\n<p>Peale programmi k\u00e4ivitamist peaksid olema meie poolt soovitud veebiaadressid k\u00e4ttesaadavad ning n\u00fc\u00fcd proovimegi samas kohtv\u00f5rgus olevast seadmest neid kontrollida. Kuna meie puhul osutus Raspberry IP aadressiks 192.168.0.101, siis leedi juhtimiseks on kasutuses vastavad URL&#8217;id:<\/p>\n<ul>\n<li>http:\/\/192.168.0.101\/led_on\u00a0 \u00a0<- sissel\u00fclitamiseks<\/li>\n<li>http:\/\/192.168.0.101\/led_off\u00a0 <- v\u00e4ljal\u00fclitamiseks<\/li>\n<\/ul>\n<p><strong>NB!<\/strong> Kui mingil p\u00f5hjusel peaks programm v\u00e4ljastama veateate &#8220;<em>socket.error: [Errno 98] Address already in use&#8221;<\/em>, siis sellega \u00fcritab operatatsioonis\u00fcsteem \u00f6elda, et mingi protsess (programm) juba kasutab porti 80. Sellisel juhul v\u00f5ib segava programmi sulgemiseks kasutada k\u00e4sku:<\/p>\n<p><code>kill -9 $(lsof -t -i:80)<\/code><br \/>\n<strong>Iseseisvaks katsetamiseks<\/strong><\/p>\n<ul>\n<li>Muutke iseseisvalt kasutatavaid universaalporte vastavalt Raspberry Pi paigaldusplaanile<\/li>\n<li>Lisage elektriskeemi veel \u00fcks leedvalgusti ning vilgutage m\u00f5lemat kordam\u00f6\u00f6da<\/li>\n<li>\u00dchendada elektriskeem nii, et leed p\u00f5leks ainult siis, kui liikumisandur tuvastab liikumise<\/li>\n<\/ul>\n<p><em>Blogi valmimist toetavad Haridus- ja Teadusministeerium ning SA Eesti Teadusagentuur.<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>J\u00e4rgnev blogipostitus on j\u00e4tk nutimaja ehitamise sarjale. Kui aga eelnev peat\u00fckk riistvara ehitamise teemal j\u00e4i mingil p\u00f5hjusel vahele, siis saab seda lugeda [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":719,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[24,34],"class_list":["post-444","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-iot","tag-software"],"_links":{"self":[{"href":"https:\/\/iot.ttu.ee\/et\/wp-json\/wp\/v2\/posts\/444","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/iot.ttu.ee\/et\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/iot.ttu.ee\/et\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/iot.ttu.ee\/et\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/iot.ttu.ee\/et\/wp-json\/wp\/v2\/comments?post=444"}],"version-history":[{"count":52,"href":"https:\/\/iot.ttu.ee\/et\/wp-json\/wp\/v2\/posts\/444\/revisions"}],"predecessor-version":[{"id":720,"href":"https:\/\/iot.ttu.ee\/et\/wp-json\/wp\/v2\/posts\/444\/revisions\/720"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/iot.ttu.ee\/et\/wp-json\/wp\/v2\/media\/719"}],"wp:attachment":[{"href":"https:\/\/iot.ttu.ee\/et\/wp-json\/wp\/v2\/media?parent=444"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/iot.ttu.ee\/et\/wp-json\/wp\/v2\/categories?post=444"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/iot.ttu.ee\/et\/wp-json\/wp\/v2\/tags?post=444"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}