I/O-liitynnän määrittely
461 531 626
Raspberry Pi voidaan kytkeä ulkopuolisiin komponentteihin ns. GPIO-liitynnän (General Purpose Input/Output) kautta. Liitynnän ohjaus voidaan toteuttaa esimerkiksi web-palvelimen ja Python-kielisten sovellusten avulla, kuten tämän sivun esimerkissä.
Luo tiedosto app.py, kopioi alla oleva sovellus siihen ja talleta se hakemistoon, jossa aiot käynnistää web-palvelimen (esimerkiksi hakemisto ~/web-server -> tiedosto ~/web-server/app.py.
# coding: utf-8 # Jotta ääkköset toimisivat nettisivulla oikein, pitää web-palvelin # määritellä käyttämään UTF-8 -koodaustaimport RPi.GPIOas GPIO # Noudetaan GPIO:n käsittelyssä tarvittava kirjasto RPi.GPIO # ja nimetään se tämän sovelluksen sisällä lyhyemmin GPIOfrom flaskimport Flask, render_template, request # render_template tarvitaan sivupohjien käyttämiseksi # request tarvitaan selaimen lähettämän URL:n tulkitsemiseksi app = Flask(__name__) GPIO.setmode(GPIO.BCM) # Käytetään Broadcomin ohjainpiirin GPIO-numeroita (BCM) # Luodaan pins-niminen assosiaatiotaulukko (dictionary), johon talletetaan kunkin # I/O-nastan numero, nimi ja tila; esimerkiksi nastan numero 23 nimeksi annetaan # GPIO 23 ja tilaksi määritellään RPi.GPIO-kirjastosta tuodulla vakiolla GPIO.LOW # "matala jännite" eli digitaalinen nolla: pins = { 23 : {'name' :'GPIO 23' ,'state' : GPIO.LOW}, 24 : {'name' :'GPIO 24' ,'state' : GPIO.LOW}, } # Käydään for-luupilla läpi pins-taulukko (eli kaikki I/O-nastat) ja asetetaan # ne yksi kerrallaan lähdöksi (vakio GPIO.OUT ja pois päältä (GPIO.LOW)for pinin pins: GPIO.setup(pin, GPIO.OUT) GPIO.output(pin, GPIO.LOW) @app.route("/" ) # määritellään RPi'n web-palvelimen juurisivu, joka löytyy "suoraan" # laitteen IP-osoitteella, esimerkiksi http://192.168.0.114/def main (): # Luetaan kunkin pinnin tila GPIO:n input-metodilla ja talletetaan # se pins-taulukon pinnikohtaiseen alkioon 'state':for pinin pins: pins[pin]['state' ] = GPIO.input(pin) # Luodaan taulukkomuuttuja templateData, jonka pins-nimiseksi alkioksi # pin-taulukko kopioidaan: templateData = {'pins' : pins } # Välitetään templateData html-sivulle main.html, minkä jälkeen kyseinen # html-sivu lähetetään selaimelle (lisätietoja: vie hiiri alla olevan rivin # yksittäisten sanojen päälle):return render_template('main.html' , **templateData) # Alla oleva koodi käsittelee sellaiset selaimen pyynnöt, joissa on I/O-pinnin # numero ja kyseiselle pinnille tehtävä operaatio (esimerkiksi antamalla selaimen # osoitteeksi http://192.168.0.114/23/off, RPi asettaa pinnin 23 pois päältä): @app.route("/<changePin>/<action>" )def action (changePin, action): # Selaimelta saatu osoite on tyypiltään merkkijono. Jatkokäsittelyä varten pinnin # numero pitää muuttaa merkkijonosta kokonaisluvuksi. Python ei osaa tehdä tätä # automaattisesti, joten tehdään muunnos funktiolla int: changePin = int(changePin) # Luetaan pinnille asetettu nimi ja talletetaan se muuttujaan deviceName: deviceName = pins[changePin]['name' ] # Mikäli selaimen osoitteessa annettu operaatio on "on", suoritetaan alla oleva koodi:if action =="on" : # Asetetaan lähtö digitaaliseen ykköstilaan: GPIO.output(changePin, GPIO.HIGH) # Muodostetaan tehdystä toimenpiteestä kertova teksti ja talletetaan se # muuttujaan message - huomaa merkkijonojen yhdistäminen +-merkillä: message ="Turned " + deviceName +" on." # Mikäli selaimen osoitteessa annettu operaatio on "off", suoritetaan alla oleva koodi:if action =="off" : # Asetetaan lähtö digitaaliseen nollatilaan: GPIO.output(changePin, GPIO.LOW) # Muodostetaan tehdystä toimenpiteestä kertova teksti kuten edellä: message ="Turned " + deviceName +" off." # Lopuksi luetaan kaikkien pinnien tilat ja talletetaan ne pins-taulukkoon:for pinin pins: pins[pin]['state' ] = GPIO.input(pin) # Kuten main-osiossa, luodaan tässäkin taulukkomuuttuja templateData, jonka # pins-nimiseksi alkioksi pin-taulukko kopioidaan: templateData = {'pins' : pins } # Kuten main-osiossa, välitetään templateData html-sivulle main.html, # minkä jälkeen kyseinen html-sivu lähetetään selaimelle:return render_template('main.html' , **templateData) # Käynnistettäessä sovellus komentoriviltä, muuttujassa __name__ on merkkijono # __main__ ja alla oleva ehtolauseke tunnistaa tämän. Tällöin suoritetaan (run) # app-niminen sovellus (joka on määritelty tämän tiedoston kolmannella käskyrivillä # app = Flask(__name__), jossa Flask on web-palvelinohjelma ja __name__ # on sille annettu parametrimuuttuja). Komentoriviltä käynnistettäessä web-palvelimelle # määritetään lisäksi alla suluissa olevat parametrit (vie hiiri tekstin päälle!):if __name__ =="__main__" : app.run(host='0.0.0.0' , port=80, debug=True)
Luo ~/web-server-hakemistoon alihakemisto templates. Luo sinne tiedosto main.html ja kopioi alla oleva sovellus siihen.
<!DOCTYPE html> <head> <title>Web-palvelin</title> <style> a { text-decoration: none; } .row { border: 3px groove; background-color: #e0e0e0; font-size: 1.5em; width: 8em; text-align: center; } </style> </head> <body> <h1>RPi Web Server</h1> {% for pin in pins %} <h2>{{ pins[pin].name }} {% if pins[pin].state == true %} is currently <strong>on</strong></h2> <div class="row"> <a href="/{{pin}}/off " role="button">Turn off</a> </div> {% else %} is currently <strong>off</strong></h2> <div class="row"> <a href="/{{pin}}/on " role="button">Turn on</a> </div> {% endif %} {% endfor %}
Web-palvelin käynnistetään pääkäyttäjänä (sudo). Jos käynnistät palvelimen muusta hakemistosta kuin missä Python-skritpi app.py sijaitsee, pitää käynnistämisen yhteydessä antaa myös polku skriptitiedostoon.
$ cd ~/web-server $ sudo python app.py
1) suhteellisen polun kautta:
$ cd ~ $ pwd /home/pi $ sudo python web-server/app.py
TAI 2) absoluuttisen polun kautta:
$ sudo python /home/pi/web-server/app.py
Lähde: Random Nerd Tutorials: Raspberry Pi Web Server using Flask to Control GPIOs