第26回 Raspberry PiのGPIOを制御する (Python編)

今回はPythonを使ってLEDの制御やスイッチの読み取りを行ってみます。PythonにはRPi.GPIOというGPIO制御用のパッケージが用意されていますので、それを使用してGPIOの制御をしてみます。

目次

今回の説明内容

今回はPythonを使ってRaspberry PiのGPIOピン制御をしてみます。PythonでRaspberry PiのGPIOを制御するには、Python Software FoundationからリリースされているRPi.GPIOという制御パッケージを利用します。

このパッケージは、Raspbian Stretchではデフォルトでインストールされていますが、Stretch Liteではインストールされていません。そこで、リモート接続タイプ機器構成の場合のみ、最初に以下の手順でRPi.GPIOをインストールしてください。

RPi.GPIOのインストール

このセクションはリモート接続タイプの機器構成のみ(Stretch Liteのみ)の作業です。

Pythonのモジュール管理は「pip」コマンドを使用します。このRaspbian Stretch Liteでは「pip」コマンドもインストールされていませんので、pipコマンドをインストールした後、RPi.GPIOパッケージをインストールします。

それではインストール前にリポジトリ情報をアップデートしましょう。

pi@raspberrypi ~ $ sudo apt-get update

ターミナルにいろいろな情報が表示されてしばらく待つとアップデートが終わります。次に、pipコマンドをインストールします。最初にpython-devモジュール群をインストールします。

pi@raspberrypi ~ $ sudo apt-get install -y python-dev

次にpython-pipモジュール群をインストールします。インストールには1〜2分時間がかかります。

pi@raspberrypi ~ $ sudo apt-get install -y python-pip

このインストールも1〜2分時間がかかります。コマンドプロンプトになったら、RPi.GPIOモジュールがインストールされているか確認します。インストールされているPythonモジュールは「pip list」というコマンドで確認します。

pi@raspberrypi ~ $ pip list
DEPRECATION: The default format will switch to columns in the future.
You can use --format=(legacy|columns) (or define a format=(legacy|columns) in your pip.conf
under the [list] section) to disable this warning.
cryptography (1.7.1)
dnspython (1.15.0)
enum34 (1.1.6)
idna (2.2)
ipaddress (1.0.17)
keyring (10.1)
keyrings.alt (1.3)
pip (9.0.1)
pyasn1 (0.1.9)
pycrypto (2.6.1)
pygobject (3.22.0)
pyxdg (0.25)
RPi.GPIO (0.6.5)
SecretStorage (2.3.1)
setuptools (33.1.1)
six (1.12.0)
wheel (0.29.0)

ちょっと探しづらいかもしれませんが、表示されたモジュールリストの中に「RPi.GPIO」があればインストールされています。もしこのモジュールが見つからない場合は、以下のコマンドでインストールします。

pi@raspberrypi ~ $ sudo pip install RPi.GPIO

以上でRPi.GPIOのインストールは完了です。

PythonでGPIOを制御する

この記事で説明する内容は以下になります。

  • 前提とする知識
  • Pythonを実行する方法
  • PythonでGPIOを制御する
  • PythonでLEDを制御する
  • Pythonでスイッチ状態を読み取る
  • LEDの点灯とスイッチのテストプログラム

前提とする知識

これからPythonでプログラムを作成してRaspberry PiのGPIOを制御していきますが、いずれかのプログラミング言語でプログラムを作成したことがあることを前提としています。

前回はPHP、今回はPythonを使用しますが、どのプログラミング言語でもでてくる、変数、型、配列、条件判断文、繰り返し構文、関数などについて、一つのプログラミング言語で理解できていれば、Pythonのプログラムも十分読み解くことができると思います。

Pythonを実行する方法

Pythonはインタープリタ型と呼ばれるプログラミング言語で、プログラム、つまりソースコードをそのまま実行していきます。例えばPHPで「Hello, world!」と画面に表示するプログラムを作成した場合、以下のようにソースコードがそのまま実行されます。

インタープリタ型に対して、コンパイラ型がありますが、これらの用語は第25回の説明をご確認いただければと思います。

インタープリタ型のPythonは、プログラムを入力してすぐに実行結果を確認することができます。まずはその動作確認をしてみましょう。

ターミナルを起動して、コマンドプロンプトから python と入力します。

pi@raspberrypi ~ $ python
Python 2.7.13 (default, Sep 26 2018, 18:42:22) 
[GCC 6.3.0 20170516] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 

というように >>> と表示されて入力待ちの状態となります。ここにPythonのコードを入力してリターンキーを押すと、すぐに実行されて結果が表示されるものはその結果が表示されます。お決まりという感じですが、Hello, world! と表示させてみましょう。何か表示する場合は「print」を使用します。

pi@raspberrypi ~ $ python
Python 2.7.9 (default, Mar  8 2015, 00:52:26) 
[GCC 4.9.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> print "Hello, world!"
Hello, world!
>>>

終了するには exit() と入力するか、Controlキー + Dを押します(Control + DはLinuxでは入力の終了を意味します)。

これでPythonの動作確認はできましたが、実際にはPythonでソースコードを書いてそれを実行することになります。Pythonのソースコードのファイル名は、拡張子が py とするのが一般的ですので、例えば test.py というファイル名でプログラムファイルを作成します。

それでは、動作確認用に「Hello, world!」と表示するPythonのソースコードファイルを作成します。

デスクトップタイプの場合はテキストエディット(gedit)を起動して以下のプログラムを入力して、ホームフォルダのdevフォルダに「test.py」というファイル名で保存します。

リモート接続タイプの場合は、Atomエディタでファイル名が「test.py」というファイルを作成して、以下のプログラムを入力、保存します。Atomエディタで新規ファイルを作成する手順は第25回の記事をご確認ください。

print "Hello, world!"

次にこのファイルを実行します。ソースコードファイルの実行方法は2通りあります。以下にそれぞれの手順を説明しますが、最初にターミナルを起動してdevフォルダに移動しておきましょう。

pi@raspberrypi ~ $ cd dev

最初の方法は、pythonコマンドを使う方法で、test.pyを実行したい場合は、

pi@raspberrypi ~/dev $ python test.py

と入力して実行します。それでは実際に試してみましょう。

pi@raspberrypi ~/dev $ python test.py
Hello, world!
pi@raspberrypi ~/dev $ 

Hello, world!と表示されましたか。何かエラーになったり表示されない場合はもう一度ソースコードを確認してみてください。

プログラムを実行するもうひとつの方法は、test.py自体を実行するというものです。test.py自体を実行する、というのはちょっとわかりづらいかもしれませんが、例えばディレクトリの内容を表示する「ls」コマンドは「ls」というファイルを実行しています。この「ls」と同様に「test.py」を直接実行しよう、というわけです。

test.pyを直接実行するには、以下の知識が必要になります。ここの部分は前回のPHPの説明と同じですので、読み飛ばして頂いて問題あまりせん。なお、読み飛ばす場合、最初の行はPythonの場合、

#!/usr/bin/python

になる点にご注意ください。

それでは、以下の順番で説明します。

  1. 起動コマンドの設定
  2. ファイルの実行権限
  3. .と..
  4. ユーザディレクトリの実行ファイルの実行方法
  5. Linuxでは先ほど作成したPythonなどのソースコードのファイル(スクリプトファイルとも呼びます)そのものを実行する場合、そのファイルをどのコマンドで実行するか指定しておく必要があります。test.py は python コマンドで実行しますので、ファイルの先頭に「pythonコマンドで実行してください」って書いておく必要があります。この書き方は、先頭は「#!」ではじめ、その後にコマンドを書きます。Raspbianではpythonは /usr/bin/ディレクトリにありますので、以下のように書くことになります。

    #!/usr/bin/python
    
    print "Hello, world!"

    これでファイルの起動コマンドの設定が終わりました。なおこのような記述を追加しても python test.py というようにpythonコマンドでも実行できます。

    次にファイルの実行権限です。

    かなり前の説明なので忘れてしまったかもしれませんが、ファイルのアクセス権について復習します。詳しくは第11回の説明をご確認いただくことにして、ここでは簡単に復習しておきます。

    ファイルのアクセス権ですが、ls -l コマンドで確認することができます。このアクセス権は以下のような意味を持っていることを説明しました。

    Access rights

    それでは、先ほど作成した test.py のアクセス権を確認してみましょう。

    pi@raspberrypi ~/dev $ ls -l test.py
    -rw-r--r-- 1 pi pi 42  5月 12 13:44 test.py

    ということで、このファイルは実行権限がないですよね。このファイルを直接実行するには実行権限をつけてしまえばOKです。

    ファイルのアクセス権を設定するには、chmod (Change Mode)コマンドを使用します。chmodコマンドのパラメータはたくさんあるのでここでは最低限のものを説明します。

    何か権限を追加する場合は「+」、削除する場合は「-」を指定し、その後に読み取り(r)、書き込み(w)、実行(x)などの種類を指定します。ここでは実行権限を追加しますので、バラメータは「+x」となります。test.py に実行権限を追加するには以下のようにします。

    pi@raspberrypi ~/dev $ chmod +x test.py

    実行権限が追加されたか確認してみましょう。

    pi@raspberrypi ~/dev $ ls -l test.py
    -rwxr-xr-x 1 pi pi 42  5月 12 13:44 test.py

    「x」がついて実行権限がつきましたよね。それでは「ls」コマンドのように実行してみましょう!

    pi@raspberrypi ~/dev $ test.py
    -bash: test.py: コマンドが見つかりません

    ファイルの実行権限が付いているのに実行できないとはどういうことなんでしょうか。この原因を理解するには、コマンドの「パス」という概念を理解する必要があります。

    今まで「ls」とコマンドを入力してディレクトリの内容を確認していましたが、lsコマンドは実際には /binディレクトリにあります。正確には「/bin/ls」と入力する必要がありますが、毎回「/bin/ls」と入力するのも面倒ですし、そもそもどのコマンドがどのディレクトリにあるかなんて覚えてられないですよね。

    ということで、ユーザがコマンドを入力した時、どのディレクトリを探すか、というコマンドを検索するパスの設定がされています。ではRaspbianではどのディレクトリがコマンドのパスになっているのでしょうか。このコマンドのパスは「$PATH」という変数に格納されていて、echoコマンドで内容を確認することができます。以下のように入力してみてください。

    pi@raspberrypi ~/dev $ echo $PATH
    /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games

    こんな感じで表示されましたでしょうか。パスは複数設定されていて「:」(コロン)で区切られています。test.pyはどこにあるかというと、ホームディレクトリに作成したと思いますので、「/home/pi」ディレクトリにあります(pwdコマンドで確認できますよね)。でも/home/piディレクトリはこのパスのリストにはありませんよね。

    ということで、test.pyに実行権限を設定しても、このtest.pyがコマンドパスにはないので「コマンドが見つかりません」といってきたわけです。

    解決方法としては、/home/piをコマンドパスに追加する方法がありますが、これはLinuxでは避けるようになっています。理由としてはセキュリティの問題からこのようになっています。

    例えば、悪意のあるユーザやウェブサイトが、ユーザのホームディレクトリに、すべてのファイルを削除する「ls」というコマンドを仕込んだとします。

    コマンドパスにユーザディレクトリがあり、それが優先されるようになっていると、ユーザがディレクトリの内容を確認しようとして「ls」と入力しただけで、先ほどのすべてのファイルを削除する「ls」が実行されてしまい、すべてのファイルが削除されてしまいます。

    このような状況を避けるためにユーザディレクトリはコマンドパスに含まれていませんので、ユーザディレクトリにある実行ファイルを実行するには、パスを指定する必要があります。

    ホームディレクトリは「/home/pi」ですので、以下のように入力すればtest.pyが実行できます。

    pi@raspberrypi ~ $ /home/pi/test.py
    Hello, world!

    でもこれだとパスの入力が面倒ですよね。そこでもうちょっとだけ入力を簡略化する方法があります。lsコマンドで「-a」オプションを指定すると不可視ファイルなども見ることができます。「ls -a」と入力してみましょう。

    pi@raspberrypi ~/dev $ ls -a
    .  ..  ._test.txt  test.py

    表示内容は異なると思いますが、左上の方に「.」と「..」というものがありますよね。設定によっては「./」や「../」と表示されているかもしれません。/はディレクトリであることを意味しています。

    この「.」と「..」ですが、これは以下を意味しています。

    記号 意味
    . 現在のディレクトリ
    .. 一つ上のディレクトリ
    (親ディレクトリ)

    「.」は今いるディレクトリを意味していますので、test.pyを実行するには、「今いるディレクトリのtest.py」という意味で、以下のように実行すればよいことになります。

    pi@raspberrypi ~ $ ./test.py
    Hello, world!

    Linuxでは、一般的にユーザが作成したプログラムは、「./ファイル名」と入力して実行しますので、このシリーズでもこの慣例に従うことにします。

    これでPythonのプログラムファイルを実行する準備ができました。

    PythonでGPIOを制御する

    PythonでRaspberry PiのGPIOを制御するには、最初に説明しましたが「RPi.GPIO」というパッケージを使用します。使用するには、Pythonのプログラムの先頭で、このパッケージを使用します、っていう宣言をすればOKです。以下のようなコードです。

    import RPi.GPIO as GPIO

    このコードについて説明します。

    importはパッケージ(モジュール・ライブラリ)を読み込む命令で、

    import RPi.GPIO

    と書くと、RPi.GPIOパッケージを読み込みます。

    RPi.GPIOには、例えば、GPIOの入出力を設定するための「setup()」という関数がありますが、この関数を使用するには、

    RPi.GPIO.setup()

    というようにドット(.)で呼び出します。ただ、毎回 RPi.GPIO と書くのは長くなりますので、importする際に別名をつけておきます。別名は「as 別名」で指定します。

    import RPi.GPIO as GPIO

    このように書くと、RPi.GPIO.setup()の代わりに

    GPIO.setup()

    で呼び出すことが可能になります。

    それではGPIO制御に必要な、以下のRPi.GPIOの関数を確認します。

    • GPIO番号指定モードの設定
      今まで何度も出てきましたが、GPIOを指定するにはGPIO番号やボードのピン番号など複数あります。この番号指定方法を設定します。
    • GPIOの入出力の設定
      GPIOを入力にするのか出力にするのか、またプルアップ、プルダウン抵抗の設定もできます。
    • GPIOの出力制御
      GPIOピンを出力モードに設定したら、出力を0か1を指定することにより、0V、3.3Vに制御できます。
    • GPIOの入力読み取り
      GPIOピンを入力モードに設定したら、ピンの電圧状態を0か1で読み取ることができます。
    • GPIOの設定リセット
      GPIOを使い終わったら、GPIOの設定をリセットできます。

    GPIO番号指定モードの設定

    GPIO番号の指定方法を2通り設定できます。一つはGPIO番号(つまり今まで使ってきましたBroadcomプロセッサのGPIOピン番号)と、もう一つはボードのピン番号です。それぞれ以下のように設定します(importはRPi.GPIO as GPIOで指定したものとします)。なお「#」以降、行末まではコメントになります。

    GPIO.setmode(GPIO.BCM)   # GPIO番号指定
    GPIO.setmode(GPIO.BOARD)   # ボードピン番号指定

    GPIOの入出力の設定

    GPIOピンを制御する前に、出力ピンなのか入力ピンなのか指定する必要があります。指定方法は以下のフォーマットです。

    GPIO.setup(ピン番号, GPIO.OUT)   # 出力指定
    GPIO.setup(ピン番号, GPIO.IN)   # 入力指定

    例えば、GPIO21ピンを出力に指定するには以下のよう書きます。

    GPIO.setup(21, GPIO.OUT)   # GPIO21番ピンを出力指定

    GPIOの出力制御

    GPIOピンの入出力モードを設定した後、ピンの制御を行うことができます。出力の制御は以下のフォーマットになります。

    GPIO.output(ピン番号, 1)   # ピンの出力を3.3Vにする
    GPIO.output(ピン番号, 0)   # ピンの出力を0Vにする

    例えば、GPIO21ピンを3.3V出力に指定するには以下のよう書きます。

    GPIO.output(21, 1)   # GPIO21番ピンを3.3V出力にする

    GPIOの入力読み取り

    GPIOピンの電圧状態を読み取る場合、以下のフォーマットとなります。

    GPIO.input(ピン番号)   # ピンの電圧状態読み取る

    実際にはピンの電圧状態が返ってきますので、結果を変数に入れたり表示します。

    print GPIO.input(ピン番号)   # ピンの電圧状態を表示する

    GPIOの設定リセット

    GPIOを使い終わったらGPIO設定をリセットします。以下のフォーマットになります。

    GPIO.cleanup()   # GPIO設定をリセット

    それではこれらのRPi.GPIOパッケージを使ってGPIO制御をしてみましょう。

    PythonでLEDを制御する

    GPIO21に接続しているLEDを1秒間点灯させてみます。なお、一定時間待つには、timeモジュールのsleep()関数を使用しますので、RPi.GPIOとtimeをインポートしています。sleep()関数の引数は秒で、time.sleep()で呼び出します。

    また、プログラムファイルに日本語でコメントを書きます。この場合、エディタでエンコーディングをUTF-8にする以外に、プログラムでもUTF-8を使ってます、って宣言する必要があります。「# coding: utf-8」と記述します。

    #!/usr/bin/python
    # coding: utf-8
    
    # モジュールをインポートする
    import RPi.GPIO as GPIO
    import time
    
    # GPIO指定をGPIO番号で行う
    GPIO.setmode(GPIO.BCM)
    
    # GPIO21ピンを出力モードに設定
    GPIO.setup(21, GPIO.OUT)
    
    # GPIO21番ピンを3.3Vに設定
    GPIO.output(21, 1)
    
    # 1秒待つ
    time.sleep(1)
    
    # GPIO21番ピンを0Vに設定
    GPIO.output(21, 0)
    
    # GPIO設定をリセット
    GPIO.cleanup()

    これがLED点滅制御の基本プログラムとなります。

    Pythonでスイッチ状態を読み取る

    GPIOピンのスイッチの状態は、ピンの入力状態を調べるGPIO.input()関数でわかります。GPIO.input()の値を表示すれば良いので、先ほど説明しました通り、print GPIO.input()でOKです。

    スイッチのテストをするために別のファイル、例えば switch.py などの名前でファイルを作成します。

    #!/usr/bin/python
    # coding: utf-8
    
    # モジュールをインポートする
    import RPi.GPIO as GPIO
    import time
    
    # GPIO指定をGPIO番号で行う
    GPIO.setmode(GPIO.BCM)
    
    # GPIO18ピンを入力モードに設定
    GPIO.setup(18, GPIO.IN)
    
    # GPIO18ピンの入力状態を表示する
    print GPIO.input(18)
    
    # GPIOピンをリセット
    GPIO.cleanup()

    先ほどと同様に、switch.pyに実行権限を追加して「./switch.py」で実行します。実行するとき、スイッチを放した状態にしたり、押した状態にしたりして値を確認してみてください。

    これで、スイッチの状態を読み取る事ができるようになりました。

    LEDの点灯とスイッチのテストプログラム

    それでは、全LEDの点灯テストとスイッチの状態を読み取るテストプログラムを作成してみましょう。テスト内容ですが、最初にLEDを順番に1秒間ずつ点灯させていき、最後にスイッチを1秒ごとに3回読み取る、ということにしたいと思います。

    なお、Pythonで指定回数、処理を繰り返すには、以下の構文を使用します。

    for 変数 in range(範囲):
        処理

    このfor構文について補足しておきます。

    Pythonでは、for文やwhile文などで処理するコードの書き方が他の言語とはちょっと違います。CやPHPなどでは

    for(i=0; i<3; i++) {
       処理1;
       処理2;
    }

    のように、forやwhileで処理するコードは{ }などで囲っています。Pythonでは、処理するコードをインデントするだけです。以下のコードでは、

    for 変数 in range(範囲):
        処理1
        処理2
    処理3

    for文で処理されるのは処理1と処理2で、処理3はfor文処理の後に実行されます。

    また、範囲は以下のように書きます。

    range(開始, 回数)

    例えば、

    range(0, 3)

    と書けば、0から開始して3回、つまり0, 1, 2という範囲になります。

    まとめると、

    for num in range(0, 3)

    と書くと、numに0, 1, 2と代入して3回繰り返しとなります。PHPで同じ処理を書くと、

    for($num=0, $num<3; $num++)

    となります。

    それでは、最初は素直にプログラムを書いてみます。

    #!/usr/bin/python
    # coding: utf-8
    
    # モジュール使用宣言
    # GPIOモジュールとtimeモジュールをimport
    import RPi.GPIO as GPIO
    import time
    
    # GPIO番号指定をBCM(GPIO番号)に設定
    GPIO.setmode(GPIO.BCM)
    
    # GPIOの初期化(LED)
    GPIO.setup(21, GPIO.OUT)
    GPIO.setup(20, GPIO.OUT)
    GPIO.setup(16, GPIO.OUT)
    GPIO.setup(12, GPIO.OUT)
    GPIO.setup(25, GPIO.OUT)
    GPIO.setup(24, GPIO.OUT)
    GPIO.setup(23, GPIO.OUT)
    
    # GPIOの初期化(スイッチ)
    GPIO.setup(18, GPIO.IN)
    
    try:
    # LEDを順番に点灯させる
    # 晴れ用LED
    GPIO.output(21, 1)
    time.sleep(1)
    GPIO.output(21, 0)
    
    # 曇り用LED
    GPIO.output(20, 1)
    time.sleep(1)
    GPIO.output(20, 0)
    
    # 雨用LED
    GPIO.output(16, 1)
    time.sleep(1)
    GPIO.output(16, 0)
    
    # 雪用LED
    GPIO.output(12, 1)
    time.sleep(1)
    GPIO.output(12, 0)
    
    # 鉄道運行表示用 緑LED
    GPIO.output(25, 1)
    time.sleep(1)
    GPIO.output(25, 0)
    
    # 鉄道運行表示用 青LED
    GPIO.output(24, 1)
    time.sleep(1)
    GPIO.output(24, 0)
    
    # 鉄道運行表示用 赤LED
    GPIO.output(23, 1)
    time.sleep(1)
    GPIO.output(23, 0)
    
    # GPIO18ピンのスイッチ状態を表示
    for num in range(0, 3):
    print GPIO.input(18)
    time.sleep(1)
    
    finally:
    # GPIOピン設定リセット
    GPIO.cleanup()

    ほとんど解説するところはないと思います。一点、今まで出てこなかった、25行目のtry:と67行目のfinallyを簡単に説明しておきます。

    try:とfinally:は対になっています。

    25行目のtry:は次の行以降、インデント部分が対象になります。具体的には26行目から65行目までがインデントされていますので、try:はこれらの行が対象になります。同様にfinally:は68行目と69行目が対象になります。

    ではtry:とfinally:は何をするかというと、try:の対象部分を実行中、何か例外処理が発生した場合、finally:の処理を行います。例えば、try:の対象部分を実行中に、Control+C(処理中断)が押された場合、処理を中断してfinally:の処理を行います。なお、finally:の対象部分はtry:の処理が何事もなく終わった場合でも処理されます。

    ところで、前回のPHPと同様、このプログラムはメンテが大変ですよね。LEDの位置が変わったり、個数が変わったり、LEDの点灯順番を変えたりすると結構いろいろ変更するところが出てきてしまいます。そこで、GPIO番号は最初に変数(LEDはリスト)として定義して、その変数を使用して制御するように書き換えました。コードの後に説明が必要な行について解説してあります。

    またコメントの書き方は、本来でしたら ”’ (シングルクウォート3個)を使ったほうがよさそうですが、前回のPHPのプログラムを一部コピペしたのでこのようになっています。

    #!/usr/bin/python
    # coding: utf-8
    
    # ------------------------
    #   モジュールインポート
    # ------------------------
    # GPIOモジュールインポート
    import RPi.GPIO as GPIO
    # timeモジュールインポート
    import time
    
    # ----------------------------
    #   GPIO番号の定義(GPIO番号)
    # ----------------------------
    # GPIOの番号の定義(LED)
    gpioLed = (21, 20, 16, 12, 25, 24, 23)
    
    # GPIOの番号の定義(スイッチ)
    gpioSwitch = 18
    
    # ------------------
    #   GPIOモード設定
    # ------------------
    # GPIO番号指定をBCM(GPIO番号)に設定
    # ボードピン番号に設定する場合は GPIO.setmode(GPIO.BOARD)にする
    GPIO.setmode(GPIO.BCM)
    
    # GPIOの初期化(LED)
    GPIO.setup(gpioLed, GPIO.OUT)
    
    # GPIOの初期化(スイッチ)
    GPIO.setup(gpioSwitch, GPIO.IN)
    
    # -------------------------
    #   LEDを配列の順番で点灯
    # -------------------------
    try:
    # 最初のLEDのGPIO番号を配列から取得して点灯させる
    # 点灯後は1秒間そのままにする
    currentLed = gpioLed[0]
    GPIO.output(currentLed, 1)
    time.sleep(1)
    
    # gpioLed配列の残りの要素を取得する
    restGpioLed = gpioLed[1:]
    
    # 残りの要素について順次点滅制御する
    for nextLed in restGpioLed:
    # 現在点灯しているLEDを消灯させる
    GPIO.output(currentLed, 0)
    # 次のLEDを点灯させる
    GPIO.output(nextLed, 1)
    # 点灯させたLEDのGPIO番号を現在のLED番号にする
    currentLed = nextLed
    # 1秒間そのままにする
    time.sleep(1)
    
    # 最後のLEDを消灯する
    GPIO.output(currentLed, 0)
    
    # ------------------------------------
    #   スイッチの状態を1秒ごとに3回表示
    # ------------------------------------
    for num in range(0, 3):
    print GPIO.input(gpioSwitch)
    time.sleep(1)
    
    # ---------------
    #   GPIOリセット
    # ---------------
    finally:
    GPIO.cleanup()

    16行目
    LEDを接続しているGPIO番号をリスト(配列)に入れておきます。GPIOの初期化や出力制御はこのリストを使って行います。順番が変わった場合やLEDを増やした場合はこのリストのみを編集すればいいようにしておきます。

    19行目
    スイッチは一つしかありませんので、変数に入れておくだけにします。

    29行目
    GPIO.setupでGPIO番号を指定しますが、リストを指定することも可能です。このように書くとプログラムがすっきりしますね。

    46行目
    PHPのプログラムでは、配列の次の要素をnextで取り出していましたが、Pythonではリストの次の要素を取り出す仕組みが見当たらなかったので、gpioLedのリストの残りの要素を取り出し、それを処理していことにしました。

    これでPytonでのLEDの点滅制御、スイッチ状態の読み取りができるようになりました。

    更新履歴

    日付 内容
    2015.12.23 新規投稿
    2019.5.12 Raspbian Stretchに対応
通知の設定
通知タイミング
guest
0 コメント
本文中にフィードバック
全てのコメントを見る
neko
neko
4 年 前

Raspberryの勉強をするのに分かりやすいサイトを探して,ここにたどり着きました.
今までよく分からなかったところがちゃんと理解できました.ありがとうございます.

一番最後のプログラムですが,このまま実行したところエラーになりました.
for num in range(0, 3):
print GPIO.input(gpioSwitch)
time.sleep(1)
のコードは,try:の処理の一部ですので,インデントが必要かと思います.
ご確認ください.

引き続き,このサイトで勉強させていただきます.

管理者
管理者
返信  neko
4 年 前

nekoさま、
ご指摘いただいてどうもありがとうございました!

すみません、ご指摘いただいたところはtry:のブロックですのでインデントが必要です。早速修正しました。

原因を確認したところ、このサイトで使用しているWordPressがスペースを削除してしまったようです。原稿はローカルでHTMLで書いているのですが、その原稿を確認したところインデントは正しい状態でした。WordPressで保存、公開するときにどうも勝手に整形されてしまったようです。

となると、他のコードも同じように勝手にインデントされているかもしれませんので、順次見直していこうと思います。

ご指摘いただいてどうもありがとうございました!

kazuooooo
kazuooooo
6 年 前

RasberryPiを始めるにあたり説明がとてもわかり易く、非常に参考になっています。ありがとうございます!(特に電気回路周りの説明は自分が中学校のころに丸暗記していたところが腹落ちしました^^)

今回の内容で少しコードの方で気になったのですがループ処理の箇所ですが特に理由が無ければ

```
try:
for currentLed in gpioLed:
GPIO.output(currentLed, 1)
time.sleep(1)
GPIO.output(currentLed, 0)

for num in range(0, 3):
print GPIO.input(gpioSwitch)
time.sleep(1)
```

のほうがシンプルでよいかと思いました。

また沢山投稿していただけるのを楽しみにしています!

管理者
管理者
返信  kazuooooo
6 年 前

kazuoooooさん、コメントどうもありがとうございました。

この記事はかなり前に書いたので、いただいたコメントのプログラムと自分のプログラムを比べて見ましたが、コメントいただいたプログラムの方が全然素直でシンプルですし、こうすべきだと思います。

自分のプログラムを見てみると、なんでこんな複雑な書き方してるんだろう、って思いました…笑

このRaspberry Pi電子工作入門ですが、Raspberry Pi本体の説明や、Raspbianのインストールあたりはかなり古い内容になっていますので、更新しなければ、、、と思いつつ時間ばかり過ぎてしまっています。

時間を見つけて古い内容は更新いたしますので、今後ともよろしくお願いいたします。

Greg Sanders
Greg Sanders
7 年 前

winのTeraPadでPythonのコード作成して、CyberduckでPIにアップして、TeraTermで実行すると、

#!/usr/bin/python: そのようなファイルやディレクトリはありません
Error: no such file “Hello, world!”

この様なエラーが出ました。
色々調べると、文字コードをUTF-8Nで保存しアップしたら、
エラーが出ずに実行できました。

UTF-8はBOM付でUTF-8NはBOM無しみたいです。

目次